[Str] add after and before helpers

This commit is contained in:
azjezz 2020-11-09 00:06:11 +01:00
parent 2bef63d5eb
commit 7ca187e4f9
28 changed files with 804 additions and 0 deletions

View File

@ -215,6 +215,7 @@ final class Loader
'Psl\Str\Byte\search',
'Psl\Str\Byte\search_ci',
'Psl\Str\Byte\search_last',
'Psl\Str\Byte\search_last_ci',
'Psl\Str\Byte\shuffle',
'Psl\Str\Byte\slice',
'Psl\Str\Byte\splice',
@ -229,6 +230,14 @@ final class Loader
'Psl\Str\Byte\uppercase',
'Psl\Str\Byte\words',
'Psl\Str\Byte\wrap',
'Psl\Str\Byte\after',
'Psl\Str\Byte\after_ci',
'Psl\Str\Byte\after_last',
'Psl\Str\Byte\after_last_ci',
'Psl\Str\Byte\before',
'Psl\Str\Byte\before_ci',
'Psl\Str\Byte\before_last',
'Psl\Str\Byte\before_last_ci',
'Psl\Str\capitalize',
'Psl\Str\capitalize_words',
'Psl\Str\chr',
@ -278,6 +287,14 @@ final class Loader
'Psl\Str\uppercase',
'Psl\Str\width',
'Psl\Str\wrap',
'Psl\Str\after',
'Psl\Str\after_ci',
'Psl\Str\after_last',
'Psl\Str\after_last_ci',
'Psl\Str\before',
'Psl\Str\before_ci',
'Psl\Str\before_last',
'Psl\Str\before_last_ci',
'Psl\invariant',
'Psl\invariant_violation',
'Psl\sequence',
@ -353,6 +370,14 @@ final class Loader
'Psl\Str\Grapheme\starts_with_ci',
'Psl\Str\Grapheme\strip_prefix',
'Psl\Str\Grapheme\strip_suffix',
'Psl\Str\Grapheme\after',
'Psl\Str\Grapheme\after_ci',
'Psl\Str\Grapheme\after_last',
'Psl\Str\Grapheme\after_last_ci',
'Psl\Str\Grapheme\before',
'Psl\Str\Grapheme\before_ci',
'Psl\Str\Grapheme\before_last',
'Psl\Str\Grapheme\before_last_ci',
];
public const INTERFACES = [

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after(string $haystack, string $needle, int $offset = 0): ?string
{
$offset = search($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_ci($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after_last(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_last($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after_last_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_last_ci($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_ci($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_last(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_last($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_last_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_last_ci($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Byte;
use Psl;
/**
* Returns the last position of the 'needle' string in the 'haystack' string,
* or null if it isn't found (case-insensitive).
*
* An optional offset determines where in the haystack (from the beginning) the
* search begins. If the offset is negative, the search will begin that many
* characters from the end of the string and go backwards. If the offset is
* out-of-bounds, an InvariantViolationException will be thrown.
*
* @psalm-pure
*
* @throws Psl\Exception\InvariantViolationException If $offset is out-of-bounds.
*/
function search_last_ci(string $haystack, string $needle, int $offset = 0): ?int
{
$haystack_length = length($haystack);
Psl\invariant($offset >= -$haystack_length && $offset <= $haystack_length, 'Offset is out-of-bounds.');
return false === ($pos = strripos($haystack, $needle, $offset)) ? null : $pos;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after(string $haystack, string $needle, int $offset = 0): ?string
{
$offset = search($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_ci($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after_last(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_last($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function after_last_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$offset = search_last_ci($haystack, $needle, $offset);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_ci($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_last(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_last($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Psl\Str\Grapheme;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
*
* @psalm-pure
*/
function before_last_ci(
string $haystack,
string $needle,
int $offset = 0
): ?string {
$length = search_last_ci($haystack, $needle, $offset);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length);
}

29
src/Psl/Str/after.php Normal file
View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$offset = search($haystack, $needle, $offset, $encoding);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null, $encoding);
}

29
src/Psl/Str/after_ci.php Normal file
View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after_ci(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$offset = search_ci($haystack, $needle, $offset, $encoding);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null, $encoding);
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after_last(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$offset = search_last($haystack, $needle, $offset, $encoding);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null, $encoding);
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function after_last_ci(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$offset = search_last_ci($haystack, $needle, $offset, $encoding);
if (null === $offset) {
return null;
}
$offset += length($needle);
return slice($haystack, $offset, null, $encoding);
}

29
src/Psl/Str/before.php Normal file
View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function before(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$length = search($haystack, $needle, $offset, $encoding);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length, $encoding);
}

29
src/Psl/Str/before_ci.php Normal file
View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function before_ci(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$length = search_ci($haystack, $needle, $offset, $encoding);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length, $encoding);
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function before_last(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$length = search_last($haystack, $needle, $offset, $encoding);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length, $encoding);
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Psl\Str;
use Psl;
/**
* @throws Psl\Exception\InvariantViolationException If the $offset is out-of-bounds.
* @throws Psl\Exception\InvariantViolationException If an invalid $encoding is provided.
*
* @psalm-pure
*/
function before_last_ci(
string $haystack,
string $needle,
int $offset = 0,
?string $encoding = null
): ?string {
$length = search_last_ci($haystack, $needle, $offset, $encoding);
if (null === $length) {
return null;
}
$length += length($needle);
return slice($haystack, 0, $length, $encoding);
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Psl\Tests\Str;
use PHPUnit\Framework\TestCase;
use Psl\Str;
final class AfterCiTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testAfter(
?string $expected,
string $haystack,
string $needle,
int $offset,
?string $encoding
): void {
static::assertSame($expected, Str\after_ci($haystack, $needle, $offset, $encoding));
}
public function provideData(): array
{
return [
[null, '', '', 0, null],
['orld!', 'Hello, World!', 'W', 0, null],
['!', '🤷!', '🤷', 0, null],
[null, 'مرحبا بكم', '', 0, null],
[null, 'مرحبا بكم', 'ß', 0, null],
[', wôrld!', 'héllö, wôrld!', 'héllö', 0, null],
[', wôrld!', 'ḫéllö, wôrld!', 'ḫéllö', 0, null],
[', wôrld!', 'ḫéllö, wôrld!', 'Ḫéllö', 0, null],
[', wôrld!', 'Ḫéllö, wôrld!', 'Ḫéllö', 0, null],
[', wôrld!', 'Ḫéllö, wôrld!', 'ḫéllö', 0, null],
['好', '你好', '你', 0, null],
['にちは世界', 'こんにちは世界', 'こん', 0, null],
['สดี', 'สวัสดี', 'วั', 0, null],
[', world!', 'Hello, world!', 'o', 0, null],
['rld!', 'Hello, world!', 'o', 7, null],
];
}
}

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace Psl\Tests\Str;
use PHPUnit\Framework\TestCase;
use Psl\Str;
final class AfterTest extends TestCase
{
/**
* @dataProvider provideData
*/
public function testAfter(
?string $expected,
string $haystack,
string $needle,
int $offset,
?string $encoding
): void {
static::assertSame($expected, Str\after($haystack, $needle, $offset, $encoding));
}
public function provideData(): array
{
return [
[null, '', '', 0, null],
['orld!', 'Hello, World!', 'W', 0, null],
['!', '🤷!', '🤷', 0, null],
[null, 'مرحبا بكم', '', 0, null],
[null, 'مرحبا بكم', 'ß', 0, null],
[', wôrld!', 'héllö, wôrld!', 'héllö', 0, null],
[', wôrld!', 'ḫéllö, wôrld!', 'ḫéllö', 0, null],
[null, 'ḫéllö, wôrld!', 'Ḫéllö', 0, null],
[', wôrld!', 'Ḫéllö, wôrld!', 'Ḫéllö', 0, null],
[null, 'Ḫéllö, wôrld!', 'ḫéllö', 0, null],
['好', '你好', '你', 0, null],
['にちは世界', 'こんにちは世界', 'こん', 0, null],
['สดี', 'สวัสดี', 'วั', 0, null],
[', world!', 'Hello, world!', 'o', 0, null],
['rld!', 'Hello, world!', 'o', 7, null],
];
}
}