From 02331add7273a160d938c5b928dfb07fd29805ea Mon Sep 17 00:00:00 2001 From: inhere Date: Thu, 25 Jan 2024 15:46:54 +0800 Subject: [PATCH] :sparkles: feat: add Ext - new add TextScanner class --- src/Arr.php | 2 +- src/Ext/TextScanner.php | 169 +++++++++++++++++++++++++++++++++ src/Util/Stream/DataStream.php | 17 +--- src/Util/UUID.php | 105 +++++++++++++------- test/Ext/TextScannerTest.php | 44 +++++++++ 5 files changed, 286 insertions(+), 51 deletions(-) create mode 100644 src/Ext/TextScanner.php create mode 100644 test/Ext/TextScannerTest.php diff --git a/src/Arr.php b/src/Arr.php index 34b7bdd..60f7234 100644 --- a/src/Arr.php +++ b/src/Arr.php @@ -13,7 +13,7 @@ /** * Class Arr - * alias of the ArrayHelper + * - alias of the ArrayHelper * * @package Toolkit\Stdlib */ diff --git a/src/Ext/TextScanner.php b/src/Ext/TextScanner.php new file mode 100644 index 0000000..9a703f2 --- /dev/null +++ b/src/Ext/TextScanner.php @@ -0,0 +1,169 @@ +source = $source; + } + + /** + * scan text token + * + * Usage: + * + * ```php + * $s = Scanner::new($source); + * while ($s->scan()) { + * $txt = $s->getText(); + * // do something + * } + * ``` + * + * @return bool + */ + public function scan(): bool + { + if ($this->done) { + return false; + } + + if ($this->start) { + $txt = strtok($this->splitToken); + } else { + $this->start = true; + Assert::notEmpty($this->source, 'The source can not be empty'); + $txt = strtok($this->source, $this->splitToken); + } + + // end + if ($txt === false) { + $this->tokText = ''; + // reset + strtok('', ''); + $this->done = true; + return false; + } + + $this->index++; + $this->tokText = $txt; + return true; + } + + /** + * @return array = [bool, string] + */ + public function nextText(): array + { + $ok = $this->scan(); + return [$ok, $this->tokText]; + } + + /** + * find next token text from given token + * + * @return array = [bool, string] + */ + public function nextToken(string $tok): array + { + $txt = strtok($tok); + if ($txt !== false) { + return [true, $txt]; + } + return [false, '']; + } + + /** + * @return string get current token text + */ + public function getText(): string + { + return $this->tokText; + } + + public function getIndex(): int + { + return $this->index; + } + + public function getSource(): string + { + return $this->source; + } + + public function setSource(string $source): void + { + $this->source = $source; + } + + public function setSplitToken(string $splitToken): void + { + $this->splitToken = $splitToken; + } + + public function current(): string + { + return $this->tokText; + } + + public function next(): void + { + $this->scan(); + } + + public function key(): int + { + return $this->index; + } + + public function valid(): bool + { + return !$this->done; + } + + public function rewind(): void + { + $this->source = ''; + $this->tokText = ''; + + $this->index = 0; + $this->start = $this->done = false; + } + +} \ No newline at end of file diff --git a/src/Util/Stream/DataStream.php b/src/Util/Stream/DataStream.php index c04654b..746f5eb 100644 --- a/src/Util/Stream/DataStream.php +++ b/src/Util/Stream/DataStream.php @@ -111,22 +111,18 @@ public static function intComparer(bool $desc = false): Closure // ---------------------- middle operations ---------------------- /** - * @param callable(array): bool $func + * @param callable(array): bool $func Will collect items that return true * @param mixed $boolExpr * * @return $this */ public function filterIf(callable $func, mixed $boolExpr): self { - if ($boolExpr) { - return $this->filter($func); - } - - return $this; + return $boolExpr ? $this->filter($func) : $this; } /** - * @param callable(mixed):bool $filterFn + * @param callable(mixed):bool $filterFn Will collect items that return true * * @return $this */ @@ -431,7 +427,6 @@ public function noneMatch(callable $matcher): bool } /** - * @template T * @return Optional */ public function findFirst(): Optional @@ -448,7 +443,6 @@ public function findFirst(): Optional } /** - * @template T * @return Optional */ public function findLast(): Optional @@ -467,7 +461,6 @@ public function findLast(): Optional } /** - * @template T * @return Optional */ public function findAny(): Optional @@ -478,7 +471,6 @@ public function findAny(): Optional /** * Find one item by given matcher * - * @template T * @param callable(mixed): bool $matcher * * @return Optional @@ -495,7 +487,6 @@ public function findOne(callable $matcher): Optional } /** - * @template T * @return Optional */ public function findRandom(): Optional @@ -506,7 +497,6 @@ public function findRandom(): Optional } /** - * @template T * @param callable(T, T): int $comparer * * @return Optional @@ -517,7 +507,6 @@ public function max(callable $comparer): Optional } /** - * @template T * @param callable(T, T): int $comparer * * @return Optional diff --git a/src/Util/UUID.php b/src/Util/UUID.php index 2cc4d7d..70b821d 100644 --- a/src/Util/UUID.php +++ b/src/Util/UUID.php @@ -11,21 +11,22 @@ use Exception; use InvalidArgumentException; -use function microtime; +use RuntimeException; use function base_convert; +use function bin2hex; +use function chr; +use function hexdec; +use function md5; +use function microtime; +use function ord; +use function pack; +use function preg_match; +use function preg_replace; use function property_exists; use function random_bytes; -use function preg_replace; -use function strlen; -use function pack; -use function md5; use function sha1; -use function chr; -use function preg_match; +use function strlen; use function substr; -use function bin2hex; -use function hexdec; -use function ord; /** * Class UUID @@ -116,25 +117,30 @@ class UUID public const VALID_UUID_REGEX = '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$'; /** - * @param int $ver - * @param string|null $node - * @param string|null $ns + * @param int $ver 1, 3, 4, 5 + * @param string|null $node for version 1, 3, 5 + * @param string|null $ns for version 3, 5 + * * @return UUID - * @throws InvalidArgumentException - * @throws Exception */ - public static function gen(int $ver = 1, string $node = null, string $ns = null): self + public static function new(int $ver = 1, string $node = null, string $ns = null): self { return self::generate($ver, $node, $ns); } + public static function v1(string $node = null): self + { + return self::generate(1, $node); + } + /** - * @param int $ver - * @param string|null $node - * @param string|null $ns + * Create a new UUID based on provided data + * + * @param int $ver 1, 3, 4, 5 + * @param string|null $node for version 1, 3, 5 + * @param string|null $ns for version 3, 5 + * * @return UUID - * @throws InvalidArgumentException - * @throws Exception */ public static function generate(int $ver = 1, string $node = null, string $ns = null): self { @@ -152,13 +158,22 @@ public static function generate(int $ver = 1, string $node = null, string $ns = case 5: return new static(static::mintName(static::SHA1, $node, $ns)); default: - throw new InvalidArgumentException('Selected version is invalid or unsupported.'); + throw new InvalidArgumentException("The version $ver is invalid or unsupported."); } } + /** + * @var string raw string bytes + */ + private string $bytes; + + /** + * @var string optimize the most common use format. + */ + private string $value; + /** * @param string $uuid - * @throws InvalidArgumentException */ protected function __construct(string $uuid) { @@ -169,7 +184,7 @@ protected function __construct(string $uuid) $this->bytes = $uuid; // Optimize the most common use - $this->string = bin2hex(substr($uuid, 0, 4)) . '-' . + $this->value = bin2hex(substr($uuid, 0, 4)) . '-' . bin2hex(substr($uuid, 4, 2)) . '-' . bin2hex(substr($uuid, 6, 2)) . '-' . bin2hex(substr($uuid, 8, 2)) . '-' . @@ -182,7 +197,6 @@ protected function __construct(string $uuid) * * @param string|null $node * @return string - * @throws Exception */ protected static function mintTime(string $node = null): string { @@ -236,11 +250,14 @@ protected static function mintTime(string $node = null): string * * @param int $bytes * @return string - * @throws Exception */ public static function randomBytes(int $bytes): string { - return random_bytes($bytes); + try { + return random_bytes($bytes); + } catch (Exception $e) { + throw new RuntimeException($e->getMessage(), $e->getCode(), $e); + } } /** @@ -285,7 +302,6 @@ protected static function makeBin(UUID|string $str, int$len): ?string * @param string|null $ns * * @return string - * @throws InvalidArgumentException */ protected static function mintName(int $ver, string $node, ?string $ns): string { @@ -329,7 +345,6 @@ protected static function mintName(int $ver, string $node, ?string $ns): string * generate random fields * * @return string - * @throws Exception */ protected static function mintRand(): string { @@ -347,7 +362,6 @@ protected static function mintRand(): string * * @param string $uuid * @return Uuid - * @throws InvalidArgumentException */ public static function import(string $uuid): UUID { @@ -372,13 +386,12 @@ public static function compare(string $a, string $b): bool /** * Import and validate an UUID * - * @param Uuid|string $uuid + * @param string $uuid * @return boolean - * @throws InvalidArgumentException */ public static function validate(string $uuid): bool { - return (bool)preg_match('~' . static::VALID_UUID_REGEX . '~', static::import($uuid)->string); + return (bool)preg_match('~' . static::VALID_UUID_REGEX . '~', static::import($uuid)->value); } /** @@ -414,7 +427,7 @@ public function __get(string $var) return null; case 'string': - return $this->__toString(); + return $this->value; case 'time': if (ord($this->bytes[6]) >> 4 === 1) { // Restore contiguous big-endian byte order @@ -429,7 +442,7 @@ public function __get(string $var) break; case 'urn': - return 'urn:uuid:' . $this->__toString(); + return 'urn:uuid:' . $this->value; case 'variant': $byte = ord($this->bytes[8]); if ($byte >= static::VAR_RES) { @@ -454,6 +467,26 @@ public function __get(string $var) return null; } + /** + * Return the UUID, not split with hyphens(-) + * + * @return string + */ + public function getRaw(): string + { + return bin2hex($this->bytes); + } + + /** + * Return the UUID. format: 00000000-0000-0000-0000-000000000000 + * + * @return string + */ + public function getValue(): string + { + return $this->value; + } + /** * Return the UUID * @@ -461,6 +494,6 @@ public function __get(string $var) */ public function __toString() { - return $this->string; + return $this->value; } } diff --git a/test/Ext/TextScannerTest.php b/test/Ext/TextScannerTest.php new file mode 100644 index 0000000..78f4e9b --- /dev/null +++ b/test/Ext/TextScannerTest.php @@ -0,0 +1,44 @@ +setSplitToken(' '); // split by space + + $ls = []; + while ($s->scan()) { + $ls[] = $s->getText(); + } + $this->assertSame(['hello', 'world', 'abc', '123'], $ls); + } + + public function testScan_line(): void + { + $src = <<scan()) { + $ls[] = $s->getText(); + } + vdump($ls); + $this->assertNotEmpty($ls); + } +}