From e1b45c2680f8d544220db8b8e0c620ca6d5a6364 Mon Sep 17 00:00:00 2001 From: azjezz Date: Sat, 3 Oct 2020 18:56:55 +0100 Subject: [PATCH] [Str] add grarpheme support --- composer.json | 3 +- src/Psl/Internal/Loader.php | 14 ++++ src/Psl/Str/Grapheme/contains.php | 30 +++++++++ src/Psl/Str/Grapheme/contains_ci.php | 30 +++++++++ src/Psl/Str/Grapheme/ends_with.php | 36 +++++++++++ src/Psl/Str/Grapheme/ends_with_ci.php | 36 +++++++++++ src/Psl/Str/Grapheme/length.php | 27 ++++++++ src/Psl/Str/Grapheme/search.php | 34 ++++++++++ src/Psl/Str/Grapheme/search_ci.php | 34 ++++++++++ src/Psl/Str/Grapheme/search_last.php | 35 ++++++++++ src/Psl/Str/Grapheme/search_last_ci.php | 35 ++++++++++ src/Psl/Str/Grapheme/slice.php | 36 +++++++++++ src/Psl/Str/Grapheme/starts_with.php | 16 +++++ src/Psl/Str/Grapheme/starts_with_ci.php | 16 +++++ src/Psl/Str/Grapheme/strip_prefix.php | 21 ++++++ src/Psl/Str/Grapheme/strip_suffix.php | 21 ++++++ tests/Psl/Str/Grapheme/ContainsCiTest.php | 32 +++++++++ tests/Psl/Str/Grapheme/ContainsTest.php | 72 +++++++++++++++++++++ tests/Psl/Str/Grapheme/EndsWithCiTest.php | 35 ++++++++++ tests/Psl/Str/Grapheme/EndsWithTest.php | 34 ++++++++++ tests/Psl/Str/Grapheme/LengthTest.php | 33 ++++++++++ tests/Psl/Str/Grapheme/SearchCiTest.php | 33 ++++++++++ tests/Psl/Str/Grapheme/SearchLastCiTest.php | 33 ++++++++++ tests/Psl/Str/Grapheme/SearchLastTest.php | 33 ++++++++++ tests/Psl/Str/Grapheme/SearchTest.php | 33 ++++++++++ tests/Psl/Str/Grapheme/SliceTest.php | 62 ++++++++++++++++++ tests/Psl/Str/Grapheme/StartsWithCiTest.php | 41 ++++++++++++ tests/Psl/Str/Grapheme/StartsWithTest.php | 41 ++++++++++++ tests/Psl/Str/Grapheme/StripPrefixTest.php | 41 ++++++++++++ tests/Psl/Str/Grapheme/StripSuffixTest.php | 48 ++++++++++++++ 30 files changed, 994 insertions(+), 1 deletion(-) create mode 100644 src/Psl/Str/Grapheme/contains.php create mode 100644 src/Psl/Str/Grapheme/contains_ci.php create mode 100644 src/Psl/Str/Grapheme/ends_with.php create mode 100644 src/Psl/Str/Grapheme/ends_with_ci.php create mode 100644 src/Psl/Str/Grapheme/length.php create mode 100644 src/Psl/Str/Grapheme/search.php create mode 100644 src/Psl/Str/Grapheme/search_ci.php create mode 100644 src/Psl/Str/Grapheme/search_last.php create mode 100644 src/Psl/Str/Grapheme/search_last_ci.php create mode 100644 src/Psl/Str/Grapheme/slice.php create mode 100644 src/Psl/Str/Grapheme/starts_with.php create mode 100644 src/Psl/Str/Grapheme/starts_with_ci.php create mode 100644 src/Psl/Str/Grapheme/strip_prefix.php create mode 100644 src/Psl/Str/Grapheme/strip_suffix.php create mode 100644 tests/Psl/Str/Grapheme/ContainsCiTest.php create mode 100644 tests/Psl/Str/Grapheme/ContainsTest.php create mode 100644 tests/Psl/Str/Grapheme/EndsWithCiTest.php create mode 100644 tests/Psl/Str/Grapheme/EndsWithTest.php create mode 100644 tests/Psl/Str/Grapheme/LengthTest.php create mode 100644 tests/Psl/Str/Grapheme/SearchCiTest.php create mode 100644 tests/Psl/Str/Grapheme/SearchLastCiTest.php create mode 100644 tests/Psl/Str/Grapheme/SearchLastTest.php create mode 100644 tests/Psl/Str/Grapheme/SearchTest.php create mode 100644 tests/Psl/Str/Grapheme/SliceTest.php create mode 100644 tests/Psl/Str/Grapheme/StartsWithCiTest.php create mode 100644 tests/Psl/Str/Grapheme/StartsWithTest.php create mode 100644 tests/Psl/Str/Grapheme/StripPrefixTest.php create mode 100644 tests/Psl/Str/Grapheme/StripSuffixTest.php diff --git a/composer.json b/composer.json index fedaad9..de914c9 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "ext-bcmath": "*", "ext-json": "*", "ext-mbstring": "*", - "ext-sodium": "*" + "ext-sodium": "*", + "ext-intl": "*" }, "require-dev": { "phpunit/phpunit": "^9.4", diff --git a/src/Psl/Internal/Loader.php b/src/Psl/Internal/Loader.php index aa03791..9d9ba8b 100644 --- a/src/Psl/Internal/Loader.php +++ b/src/Psl/Internal/Loader.php @@ -336,6 +336,20 @@ final class Loader 'Psl\Hash\equals', 'Psl\Hash\Hmac\hash', 'Psl\Hash\Hmac\algorithms', + 'Psl\Str\Grapheme\contains', + 'Psl\Str\Grapheme\contains_ci', + 'Psl\Str\Grapheme\ends_with', + 'Psl\Str\Grapheme\ends_with_ci', + 'Psl\Str\Grapheme\length', + 'Psl\Str\Grapheme\search', + 'Psl\Str\Grapheme\search_ci', + 'Psl\Str\Grapheme\search_last', + 'Psl\Str\Grapheme\search_last_ci', + 'Psl\Str\Grapheme\slice', + 'Psl\Str\Grapheme\starts_with', + 'Psl\Str\Grapheme\starts_with_ci', + 'Psl\Str\Grapheme\strip_prefix', + 'Psl\Str\Grapheme\strip_suffix', ]; public const INTERFACES = [ diff --git a/src/Psl/Str/Grapheme/contains.php b/src/Psl/Str/Grapheme/contains.php new file mode 100644 index 0000000..daf207d --- /dev/null +++ b/src/Psl/Str/Grapheme/contains.php @@ -0,0 +1,30 @@ + $total_length) { + return false; + } + + /** @psalm-suppress MissingThrowsDocblock */ + $position = search_last($string, $suffix); + if (null === $position) { + return false; + } + + return $position + $suffix_length === $total_length; +} diff --git a/src/Psl/Str/Grapheme/ends_with_ci.php b/src/Psl/Str/Grapheme/ends_with_ci.php new file mode 100644 index 0000000..9d34662 --- /dev/null +++ b/src/Psl/Str/Grapheme/ends_with_ci.php @@ -0,0 +1,36 @@ + $total_length) { + return false; + } + + /** @psalm-suppress MissingThrowsDocblock */ + $position = search_last_ci($string, $suffix); + if (null === $position) { + return false; + } + + return $position + $suffix_length === $total_length; +} diff --git a/src/Psl/Str/Grapheme/length.php b/src/Psl/Str/Grapheme/length.php new file mode 100644 index 0000000..c0ead6e --- /dev/null +++ b/src/Psl/Str/Grapheme/length.php @@ -0,0 +1,27 @@ += -$haystack_length && $offset <= $haystack_length, 'Offset is out-of-bounds.'); + + return false === ($pos = grapheme_strrpos($haystack, $needle, $offset)) ? + null : + $pos; +} diff --git a/src/Psl/Str/Grapheme/search_last_ci.php b/src/Psl/Str/Grapheme/search_last_ci.php new file mode 100644 index 0000000..d1295e4 --- /dev/null +++ b/src/Psl/Str/Grapheme/search_last_ci.php @@ -0,0 +1,35 @@ += -$haystack_length && $offset <= $haystack_length, 'Offset is out-of-bounds.'); + + return false === ($pos = grapheme_strripos($haystack, $needle, $offset)) ? + null : + $pos; +} diff --git a/src/Psl/Str/Grapheme/slice.php b/src/Psl/Str/Grapheme/slice.php new file mode 100644 index 0000000..0b2a5f0 --- /dev/null +++ b/src/Psl/Str/Grapheme/slice.php @@ -0,0 +1,36 @@ += 0, 'Expected a non-negative length.'); + $string_length = length($string); + $offset = Psl\Internal\validate_offset($offset, $string_length); + + if (0 === $offset && (null === $length || $string_length <= $length)) { + return $string; + } + + if (null === $length) { + return (string) grapheme_substr($string, $offset); + } + + return (string) grapheme_substr($string, $offset, $length); +} diff --git a/src/Psl/Str/Grapheme/starts_with.php b/src/Psl/Str/Grapheme/starts_with.php new file mode 100644 index 0000000..ba84532 --- /dev/null +++ b/src/Psl/Str/Grapheme/starts_with.php @@ -0,0 +1,16 @@ +expectException(Exception\InvariantViolationException::class); + + Grapheme\slice('Hello', 0, -1); + } + + public function testSliceThrowsForOutOfBoundOffset(): void + { + $this->expectException(Exception\InvariantViolationException::class); + + Grapheme\slice('Hello', 10); + } + + public function testSliceThrowsForNegativeOutOfBoundOffset(): void + { + $this->expectException(Exception\InvariantViolationException::class); + + Grapheme\slice('hello', -6); + } +} diff --git a/tests/Psl/Str/Grapheme/StartsWithCiTest.php b/tests/Psl/Str/Grapheme/StartsWithCiTest.php new file mode 100644 index 0000000..51d3588 --- /dev/null +++ b/tests/Psl/Str/Grapheme/StartsWithCiTest.php @@ -0,0 +1,41 @@ +