{"id":19387002,"url":"https://github.com/bermudaphp/stringy","last_synced_at":"2026-05-18T07:31:31.701Z","repository":{"id":62493392,"uuid":"246912947","full_name":"bermudaphp/stringy","owner":"bermudaphp","description":"A comprehensive PHP string manipulation library with full Unicode support","archived":false,"fork":false,"pushed_at":"2025-05-21T20:12:52.000Z","size":333,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-08T21:25:50.526Z","etag":null,"topics":["immutable","multibyte","string","string-manipulation","strings","unicode","utf-8"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bermudaphp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-12T19:16:28.000Z","updated_at":"2025-05-21T20:12:56.000Z","dependencies_parsed_at":"2024-02-07T00:29:58.420Z","dependency_job_id":"dd3d3805-c12e-4c0d-8389-43016dce6363","html_url":"https://github.com/bermudaphp/stringy","commit_stats":{"total_commits":212,"total_committers":2,"mean_commits":106.0,"dds":"0.17924528301886788","last_synced_commit":"c121c035fcd03a31b910e9bde742dfb6085bcb0e"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/bermudaphp/stringy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bermudaphp%2Fstringy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bermudaphp%2Fstringy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bermudaphp%2Fstringy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bermudaphp%2Fstringy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bermudaphp","download_url":"https://codeload.github.com/bermudaphp/stringy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bermudaphp%2Fstringy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33169177,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T05:43:36.989Z","status":"ssl_error","status_checked_at":"2026-05-18T05:43:19.133Z","response_time":71,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["immutable","multibyte","string","string-manipulation","strings","unicode","utf-8"],"created_at":"2024-11-10T10:08:04.794Z","updated_at":"2026-05-18T07:31:31.694Z","avatar_url":"https://github.com/bermudaphp.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bermudaphp\\stringy\n\n[![PHP Version Require](https://img.shields.io/badge/php-%3E%3D8.4-brightgreen.svg)](https://php.net/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/bermudaphp/stringy/blob/master/LICENSE)\n[![GitHub Tests](https://img.shields.io/github/actions/workflow/status/bermudaphp/stringy/tests.yml?branch=master\u0026label=tests)](https://github.com/bermudaphp/stringy/actions/workflows/tests.yml)\n\n*Read this documentation in [Russian](README.ru.md).*\n\n## Overview\n\nbermudaphp/stringy is a comprehensive PHP string manipulation library with full Unicode support. It provides both immutable and mutable string classes with a consistent API, making string operations more reliable and convenient compared to native PHP functions.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Basic Concepts](#basic-concepts)\n- [Class Examples](#class-examples)\n  - [Str (Immutable)](#str-immutable)\n  - [StrMutable (Mutable)](#strmutable-mutable)\n  - [StringIterator](#stringiterator)\n  - [Stringy (Static Utility)](#stringy-static-utility)\n  - [ClsHelper (Class Name Utility)](#clshelper-class-name-utility)\n- [Working with Multibyte Strings](#working-with-multibyte-strings)\n- [License](#license)\n- [Contributing](#contributing)\n\n## Installation\n\n```bash\ncomposer require bermudaphp/stringy\n```\n\n## Basic Concepts\n\nThe library provides two main string classes:\n\n- **Str**: Immutable string class. Operations return new string instances without modifying the original.\n- **StrMutable**: Mutable string class. Operations modify the string in place and return the same instance.\n\nBoth implement the **StringInterface** contract, providing a consistent API for string manipulation.\n\n## Class Examples\n\n### Str (Immutable)\n\nThe immutable string class returns a new instance for every operation that would change the string.\n\n#### Creating Immutable Strings\n\n```php\nuse Bermuda\\Stdlib\\Str;\n\n// Create from string\n$str = Str::from('Hello World');\n\n// Create with specific encoding\n$russianStr = Str::from('Привет мир', 'UTF-8');\n\n// Create through constructor\n$str = new Str('Hello World');\n\n// alternative\n$str = Stringy::of('Hello World');\n```\n## Lazy Initialization with createLazy()\n\nThe `createLazy()` static method allows you to create lazily initialized string objects that are only constructed when actually accessed. This can significantly improve performance by delaying expensive operations until they're truly needed.\n\n```php\n// Create a lazy-initialized string object\n$lazy = \\Bermuda\\Stdlib\\Str::createLazy(static function (\\Bermuda\\Stdlib\\Str $str) {\n    $str-\u003e__construct('construct call');\n});\n\n// No initialization occurs until the object is accessed\necho $lazy-\u003evalue; // Triggers initialization: \"construct call\"\n```\n\n### How It Works\nUnlike traditional objects that are initialized immediately, lazy ghost objects:\n\nCreate a minimal placeholder object initially.  \nOnly execute your initializer function when a property or method is accessed.  \nInitialize the object just-in-time with the values you specify.\n\n### When to Use\nLazy initialization is particularly valuable when:\n\nResource-heavy initialization: Loading data from files, databases, or APIs.  \nConditional usage: When objects may not be used in all code paths.  \nPerformance optimization: Delaying expensive operations until absolutely necessary.  \nMemory management: Reducing memory usage by not initializing unused objects.\n\n### Advanced Example\n```php\n// Creating multiple lazy string objects for a report\n$reportFields = [\n    'title' =\u003e Str::createLazy(function($str) use ($reportId) {\n        $data = $database-\u003efetchReportTitle($reportId);\n        $str-\u003e__construct($data);\n    }),\n    'summary' =\u003e Str::createLazy(function($str) use ($reportId) {\n        $data = $database-\u003efetchReportSummary($reportId);\n        $str-\u003e__construct($data);\n    }),\n    'content' =\u003e Str::createLazy(function($str) use ($reportId) {\n        // This potentially large content is only loaded if actually displayed\n        $data = $database-\u003efetchReportContent($reportId);\n        $str-\u003e__construct($data);\n    })\n];\n\n// Only the title and summary are initialized - content remains lazy\necho $reportFields['title']-\u003etoUpperCase();\necho $reportFields['summary']-\u003etruncate(100);\n\n// If this condition is false, content is never loaded from the database\nif ($showFullReport) {\n    echo $reportFields['content'];\n}\n```\n\n#### Basic Properties\n\n```php\n$str = Str::from('Hello');\n\n// Get the underlying string value\necho $str-\u003evalue;                // \"Hello\"\n\n// Get the current encoding\necho $str-\u003eencoding;             // \"UTF-8\" (default)\n\n// Check if string contains multibyte characters\nvar_dump($str-\u003eisMultibyte);     // bool(false)\n\n$russianStr = Str::from('Привет');\nvar_dump($russianStr-\u003eisMultibyte); // bool(true)\n```\n\n#### String Conversion and Basic Operations\n\n```php\n$str = Str::from('Hello World');\n\n// Convert to string\necho $str-\u003etoString();           // \"Hello World\"\necho $str;                       // \"Hello World\" (uses __toString())\n\n// Create a copy\n$copy = $str-\u003ecopy();           // Creates new Str instance with same value\n$copy === $str;                 // false\n\n// Encode to different character set\n$latin1 = $str-\u003eencode('ISO-8859-1');\n\n// Get byte count (different from character count for multibyte strings)\necho $str-\u003egetBytes();          // 11\n\n// Get string length in characters\necho $str-\u003elength();            // 11\necho count($str);               // 11 (using Countable interface)\n\n// Check if string is empty\nvar_dump($str-\u003eisEmpty());      // bool(false)\nvar_dump(Str::from('')-\u003eisEmpty()); // bool(true)\n\n// Check if string is blank (empty or only whitespace)\nvar_dump(Str::from(' ')-\u003eisBlank()); // bool(true)\n```\n\n#### Character Access\n\n```php\n$str = Str::from('Hello World');\n\n// Get character at position\necho $str-\u003echarAt(0);           // \"H\"\necho $str-\u003echarAt(6);           // \"W\"\necho $str-\u003echarAt(-1);          // \"d\" (negative indices count from end)\n\n// Get character as a new string object\n$firstChar = $str-\u003eat(0);       // Returns Str('H')\n$lastChar = $str-\u003eat(-1);       // Returns Str('d')\n\n// Get first and last characters\n$first = $str-\u003efirst();         // Returns Str('H')\n$last = $str-\u003elast();           // Returns Str('d')\n\n// Check if position exists\nvar_dump($str-\u003ehas(5));         // bool(true)\nvar_dump($str-\u003ehas(20));        // bool(false)\n\n// Get index bounds\necho $str-\u003efirstIndex();        // 0\necho $str-\u003elastIndex();         // 10\n\n// Array access (for reading only in Str)\necho $str[0];                   // \"H\"\necho $str[-1];                  // \"d\"\n```\n\n#### Substring Operations\n\n```php\n$str = Str::from('Hello World');\n\n// Extract substring\necho $str-\u003esubstring(0, 5);     // \"Hello\"\necho $str-\u003esubstring(6);        // \"World\" (to the end)\necho $str-\u003esubstring(-5);       // \"World\" (from 5th last character to end)\n\n// Get start/end of string\necho $str-\u003estart(5);            // \"Hello\"\necho $str-\u003eend(5);              // \"World\"\n\n// Remove from start/end\necho $str-\u003eremoveStart(6);      // \"World\"\necho $str-\u003eremoveEnd(6);        // \"Hello\"\n\n// Get substring between delimiters\necho $str-\u003ebetween('H', 'o');   // \"ell\"\n\n// Get substring before/after\necho $str-\u003ebefore('World');     // \"Hello \"\necho $str-\u003eafter('Hello');      // \" World\"\n\n// Include delimiter in before/after\necho $str-\u003ebefore('World', true);  // \"Hello W\"\necho $str-\u003eafter('Hello', true);   // \"Hello World\"\n\n// Split into two parts\nlist($first, $second) = $str-\u003esplit(' ');\necho $first;                    // \"Hello\"\necho $second;                   // \"World\"\n\n// Split by delimiter\n$parts = $str-\u003eexplode(' ');    // Returns array of Str objects\n$parts = $str-\u003eexplode(' ', PHP_INT_MAX, true); // Returns array of strings\n```\n\n#### String Comparison\n\n```php\n$str = Str::from('Hello World');\n\n// Compare with another string\nvar_dump($str-\u003eequals('Hello World'));  // bool(true)\nvar_dump($str-\u003eequals('hello world'));  // bool(false)\nvar_dump($str-\u003eequals('hello world', false)); // bool(true) - case insensitive\n\n// Compare with any of multiple strings\nvar_dump($str-\u003eequalsAny(['Hello', 'World', 'Hello World'])); // bool(true)\n\n// Check if starts with\nvar_dump($str-\u003estartsWith('Hello'));    // bool(true)\nvar_dump($str-\u003estartsWith(['Hi', 'Hello'])); // bool(true)\nvar_dump($str-\u003estartsWith('hello', false)); // bool(true) - case insensitive\n\n// Check if ends with\nvar_dump($str-\u003eendsWith('World'));      // bool(true)\nvar_dump($str-\u003eendsWith(['Earth', 'World'])); // bool(true)\n\n// Check if contains\nvar_dump($str-\u003econtains('lo Wo'));      // bool(true)\nvar_dump($str-\u003econtains(['lo', 'Wo'])); // bool(true)\n\n// Check if contains all\nvar_dump($str-\u003econtainsAll(['Hello', 'World'])); // bool(true)\n```\n\n#### Search Operations\n\n```php\n$str = Str::from('Hello World, Hello Earth');\n\n// Find position of substring\necho $str-\u003eindexOf('Hello');       // 0\necho $str-\u003eindexOf('Hello', 1);    // 13 (starting from position 1)\necho $str-\u003eindexOf('hello', 0, false); // 0 (case insensitive)\nvar_dump($str-\u003eindexOf('Bye'));    // NULL (not found)\n\n// Find last position of substring\necho $str-\u003elastIndexOf('Hello');   // 13\n\n// Count occurrences\necho $str-\u003ecountSubstr('Hello');   // 2\necho $str-\u003ecountSubstr('hello', false); // 2 (case insensitive)\n```\n\n#### Case Conversion\n\n```php\n$str = Str::from('hello world');\n\n// Convert to uppercase/lowercase\necho $str-\u003etoUpperCase();         // \"HELLO WORLD\"\necho $str-\u003etoLowerCase();         // \"hello world\"\n\n// Capitalize first character\necho $str-\u003ecapitalize();          // \"Hello world\"\n\n// Uncapitalize first character\necho Str::from('Hello World')-\u003euncapitalize(); // \"hello World\"\n\n// Capitalize each word\necho $str-\u003ecapitalizeWords();      // \"Hello World\"\n\n// Swap case of each character\necho Str::from('Hello')-\u003eswapCase(); // \"hELLO\"\n\n// Title case (smarter capitalization)\necho $str-\u003etitleize();            // \"Hello World\"\necho $str-\u003etitleize(['of', 'the']); // \"Hello World\" (with ignored words)\n```\n\n#### Format Conversion\n\n```php\n$str = Str::from('hello_world-example');\n\n// Convert to different formats\necho $str-\u003etoCamelCase();        // \"helloWorldExample\"\necho $str-\u003etoPascalCase();       // \"HelloWorldExample\"\necho $str-\u003etoSnakeCase();        // \"hello_world_example\"\necho $str-\u003etoKebabCase();        // \"hello-world-example\"\n\n// Custom delimiter\necho $str-\u003edelimit('.');         // \"hello.world.example\"\n```\n\n#### Whitespace Handling\n\n```php\n$str = Str::from('  Hello World  ');\n\n// Trim whitespace\necho $str-\u003etrim();               // \"Hello World\"\necho $str-\u003etrimStart();          // \"Hello World  \"\necho $str-\u003etrimEnd();            // \"  Hello World\"\n\n// Custom characters to trim\necho Str::from('__Hello__')-\u003etrim('_'); // \"Hello\"\n\n// Remove all whitespace\necho $str-\u003estripWhitespace();    // \"HelloWorld\"\n\n// Collapse multiple whitespace to single space\necho Str::from('Hello  World')-\u003ecollapseWhitespace(); // \"Hello World\"\n```\n\n#### String Modification\n\n```php\n$str = Str::from('Hello World');\n\n// Insert at position\necho $str-\u003einsert(' Dear', 5);   // \"Hello Dear World\"\n\n// Pad string\necho $str-\u003epad('*', 15);         // \"**Hello World**\"\necho $str-\u003epadStart('-', 15);    // \"----Hello World\"\necho $str-\u003epadEnd('=', 15);      // \"Hello World====\"\n\n// Wrap with character\necho $str-\u003ewrap('\"');            // \"\\\"Hello World\\\"\"\n\n// Check if wrapped\nvar_dump(Str::from('\"Hello\"')-\u003eisWrapped('\"')); // bool(true)\n\n// Add to start/end\necho $str-\u003eprepend('Dear ');     // \"Dear Hello World\"\necho $str-\u003eappend('!');          // \"Hello World!\"\n\n// Add prefix/suffix if not exists\necho $str-\u003eensurePrefix('Hello '); // \"Hello World\" (unchanged)\necho $str-\u003eensureSuffix('!');    // \"Hello World!\"\n\n// Remove prefix/suffix\necho Str::from('HelloWorld')-\u003eremoveSuffix('World'); // \"Hello\"\necho Str::from('HelloWorld')-\u003eremovePrefix('Hello'); // \"World\"\n```\n\n#### Search and Replace\n\n```php\n$str = Str::from('Hello World');\n\n// Replace text\necho $str-\u003ereplace('World', 'Earth'); // \"Hello Earth\"\necho $str-\u003ereplace(['Hello', 'World'], ['Hi', 'Earth']); // \"Hi Earth\"\necho $str-\u003ereplace('world', 'Earth', false); // \"Hello Earth\" (case insensitive)\n\n// Replace first/last occurrence\necho Str::from('Hello Hello')-\u003ereplaceFirst('Hello', 'Hi'); // \"Hi Hello\"\necho Str::from('Hello Hello')-\u003ereplaceLast('Hello', 'Hi');  // \"Hello Hi\"\n\n// Replace with pattern\necho $str-\u003ereplaceBy('/[aeiou]/i', '*'); // \"H*ll* W*rld\"\n\n// Replace with callback\n$result = $str-\u003ereplaceCallback('/[A-Z]/u', function($match) {\n    return '_' . strtolower($match[0]);\n}); // \"_hello _world\"\n```\n\n#### String Transformation\n\n```php\n$str = Str::from('Hello World');\n\n// Reverse\necho $str-\u003ereverse();           // \"dlroW olleH\"\n\n// Shuffle characters\necho $str-\u003eshuffle();           // Random order, e.g. \"ldWroHl eol\"\n\n// Repeat\necho Str::from('Hi ')-\u003erepeat(3); // \"Hi Hi Hi \"\n\n// Truncate\necho Str::from('This is a long sentence')-\u003etruncate(10); // \"This is...\"\necho Str::from('This is a long sentence')-\u003etruncate(10, '---'); // \"This is---\"\necho Str::from('This is a long sentence')-\u003etruncate(10, '...', true); // \"This...\"\n\n// Transform with callback\necho $str-\u003etransform(function($s) {\n    return strtoupper($s) . '!';\n}); // \"HELLO WORLD!\"\n\n// Tabs and spaces\necho Str::from(\"Hello\\tWorld\")-\u003etabsToSpaces(2); // \"Hello  World\"\necho Str::from(\"Hello  World\")-\u003espacesToTabs(2); // \"Hello\\tWorld\"\n\n// Format with sprintf\necho Str::from('Hello, %s!')-\u003eformat('John'); // \"Hello, John!\"\n```\n\n#### Type Validation and Conversion\n\n```php\n$str = Str::from('123');\n\n// Check types\nvar_dump($str-\u003eisNumeric());     // bool(true)\nvar_dump($str-\u003eisAlpha());       // bool(false)\nvar_dump($str-\u003eisAlphanumeric()); // bool(true)\nvar_dump($str-\u003eisHex());         // bool(true)\nvar_dump($str-\u003eisUpperCase());   // bool(false)\nvar_dump($str-\u003eisLowerCase());   // bool(false)\nvar_dump($str-\u003ehasUpperCase());  // bool(false)\nvar_dump($str-\u003ehasLowerCase());  // bool(false)\nvar_dump($str-\u003ehasDigits());     // bool(true)\nvar_dump($str-\u003ehasSymbols());    // bool(false)\n\n// Convert to types\necho $str-\u003etoNumber();           // int(123)\nvar_dump(Str::from('true')-\u003etoBoolean()); // bool(true)\nvar_dump(Str::from('true')-\u003eisBoolean()); // bool(true)\n\n// JSON operations\nvar_dump(Str::from('{\"a\":1}')-\u003eisJson()); // bool(true)\necho Str::from('Hello')-\u003etoJson(); // \"\\\"Hello\\\"\"\n\n// Other type checks\nvar_dump(Str::from('a:1:{s:1:\"a\";i:1;}')-\u003eisSerialized()); // bool(true)\nvar_dump(Str::from('SGVsbG8=')-\u003eisBase64()); // bool(true)\nvar_dump(Str::from('2023-05-17')-\u003eisDate()); // bool(true)\n\n// Convert to date\n$date = Str::from('2023-05-17')-\u003etoDate();\n```\n\n#### String Segmentation\n\n```php\n$str = Str::from(\"Hello\\nWorld\\nExample\");\n\n// Split into lines\n$lines = $str-\u003elines();          // Array of Str objects, one per line\n\n// Split into words\n$words = Str::from('Hello World Example')-\u003ewords(); // [\"Hello\", \"World\", \"Example\"]\n\n// Convert to array of characters\n$chars = $str-\u003etoArray();        // [\"H\", \"e\", \"l\", \"l\", \"o\", ... ]\n```\n\n#### Regular Expressions\n\n```php\n$str = Str::from('Hello 123 World');\n\n// Match pattern\n$found = $str-\u003ematch('/\\d+/', $matches);\nvar_dump($found);               // bool(true)\necho $matches[0];               // \"123\"\n\n// Match all occurrences\n$found = $str-\u003ematchAll('/\\w+/', $matches);\nvar_dump($matches[0]);          // Array with all words\n```\n\n#### Other Operations\n\n```php\n$str = Str::from('Hello World');\n\n// Hash the string\necho $str-\u003ehash();              // SHA-256 hash\necho $str-\u003ehash('md5');         // MD5 hash\n\n// ASCII conversion\necho Str::from('Café')-\u003etoAscii(); // \"Cafe\"\n\n// Output\n$str-\u003eprint();                  // Outputs \"Hello World\"\n\n// Iterate through characters\n$str-\u003eeach(function($char, $index) {\n    echo \"$index: $char\\n\";\n    return true; // Continue iteration\n});\n```\n\n#### Iterator Usage\n\n```php\n$str = Str::from('Hello');\n\n// Get iterator\n$iterator = $str-\u003egetIterator();\n\n// Use in foreach\nforeach ($iterator as $index =\u003e $char) {\n    echo \"$index: $char\\n\";\n}\n```\n\n### StrMutable (Mutable)\n\nThe mutable string class modifies the string in place and returns the same instance for method chaining.\n\n#### Creating Mutable Strings\n\n```php\nuse Bermuda\\Stdlib\\StrMutable;\n\n// Create from string\n$str = StrMutable::create('Hello World');\n\n// Create with specific encoding\n$russianStr = StrMutable::create('Привет мир', 'UTF-8');\n\n// Create through constructor\n$str = new StrMutable('Hello World');\n\n// alternative\n$str = Stringy::mutable('Hello World');\n\n// Set string value directly\n$str = StrMutable::create('Hello');\n$str-\u003esetString('New Value');\n```\n\nMost methods in StrMutable have the same API as Str, but modify the string in place:\n\n```php\n$str = StrMutable::create('Hello World');\n\n// Chain operations\n$str-\u003etoUpperCase()\n    -\u003etrim()\n    -\u003ereplace('WORLD', 'EARTH');\n\necho $str; // \"HELLO EARTH\"\n\n// Substring modifies in place\n$str-\u003esubstring(0, 5);\necho $str; // \"HELLO\"\n```\n\n#### Array Access (Mutable)\n\n```php\n$str = StrMutable::create('Hello');\n\n// Read\necho $str[1];  // \"e\"\n\n// Write\n$str[0] = 'J';\necho $str;     // \"Jello\"\n\n// Remove character\nunset($str[4]);\necho $str;     // \"Jell\"\n```\n\n### StringIterator\n\nThe StringIterator class allows character-by-character iteration with various navigation methods.\n\n#### Creating and Basic Usage\n\n```php\nuse Bermuda\\Stdlib\\StringIterator;\n\n// Create directly\n$iterator = new StringIterator('Hello');\n\n// Create through string object\n$str = Str::from('World');\n$iterator = $str-\u003egetIterator();\n\n// Basic iteration\nwhile ($iterator-\u003evalid()) {\n    echo $iterator-\u003ecurrent();\n    $iterator-\u003enext();\n}\n// Outputs: \"World\"\n\n// Get the string\necho $iterator-\u003e__toString(); // \"World\"\n\n// Create new iterator with different string\n$newIterator = $iterator-\u003ewithString('Hello');\n```\n\n#### Navigation\n\n```php\n$iterator = new StringIterator('Hello World');\n\n// Get current state\necho $iterator-\u003ecurrent();   // \"H\" (initial position is 0)\necho $iterator-\u003ekey();       // 0 (current position)\n\n// Move forward/backward\n$iterator-\u003enext();\necho $iterator-\u003ecurrent();   // \"e\"\n\n$iterator-\u003eforward(2);       // Move 2 steps forward\necho $iterator-\u003ecurrent();   // \"l\"\n\n$iterator-\u003ebackward();       // Move 1 step back\necho $iterator-\u003ecurrent();   // \"e\"\n\n// Jump to position\n$iterator-\u003emoveTo(6);\necho $iterator-\u003ecurrent();   // \"W\"\n\n// Reset position\n$iterator-\u003erewind();\necho $iterator-\u003ekey();       // 0\n\n// Check position\nvar_dump($iterator-\u003eisStart()); // bool(true)\nvar_dump($iterator-\u003eisEnd());   // bool(false)\n\n$iterator-\u003emoveTo($iterator-\u003elastIndex());\nvar_dump($iterator-\u003eisEnd());   // bool(false)\n\n$iterator-\u003enext();\nvar_dump($iterator-\u003eisEnd());   // bool(true)\nvar_dump($iterator-\u003evalid());   // bool(false)\n```\n\n#### Reading\n\n```php\n$iterator = new StringIterator('Hello World');\n\n// Read next characters\n$iterator-\u003emoveTo(6);\necho $iterator-\u003ereadNext(5);    // \"World\"\n\n// Read to the end (when length is null)\n$iterator-\u003emoveTo(6);\necho $iterator-\u003ereadNext();     // \"World\"\n```\n\n### Stringy (Static Utility)\n\nThe Stringy class provides static utility methods for string manipulation.\n\n```php\nuse Bermuda\\Stdlib\\Stringy;\n\n// Convert string format\necho Stringy::delimit('HelloWorld', '-');           // \"hello-world\"\necho Stringy::delimit('hello_world-example', '.'); // \"hello.world.example\"\n\n// Trim whitespace\necho Stringy::trim('  Hello  ');                    // \"Hello\"\necho Stringy::trimStart('  Hello  ');               // \"Hello  \"\necho Stringy::trimEnd('  Hello  ');                 // \"  Hello\"\n\n// With custom characters\necho Stringy::trim('__Hello__', '_');               // \"Hello\"\n\n// Multibyte support\necho Stringy::trim('  Привет  ');                   // \"Привет\"\n```\n\n### ClsHelper (Class Name Utility)\n\nThe ClsHelper class provides utilities for working with class names and namespaces.\n\n```php\nuse Bermuda\\Stdlib\\ClsHelper;\n\n$className = 'Bermuda\\\\Stringy\\\\StrMutable';\n\n// Get namespace part\necho ClsHelper::namespace($className);    // \"Bermuda\\\\Stringy\"\n\n// Get basename (class without namespace)\necho ClsHelper::basename($className);     // \"StrMutable\"\n\n// Split into namespace and class name\n$parts = ClsHelper::split($className);\n// Returns: [0 =\u003e 'Bermuda\\\\Stringy', 1 =\u003e 'StrMutable']\n\n// Validate class names\nvar_dump(ClsHelper::isValidName('MyClass'));          // bool(true)\nvar_dump(ClsHelper::isValidName('Vendor\\\\MyClass'));  // bool(true)\nvar_dump(ClsHelper::isValidName('Vendor\\\\MyClass', false)); // bool(false) - no namespace allowed\nvar_dump(ClsHelper::isValidName('0InvalidClass'));    // bool(false)\n```\n\n## Working with Multibyte Strings\n\nAll methods in Bermuda\\Stringy properly handle multibyte strings, ensuring correct character handling for non-Latin alphabets and special characters:\n\n### Basic Multibyte Operations\n\n```php\n// Create with specific encoding\n$russian = Str::from('Привет, мир!', 'UTF-8');\n$chinese = Str::from('你好，世界！', 'UTF-8');\n$arabic = Str::from('مرحبا بالعالم!', 'UTF-8');\n\n// Character count vs byte count\necho $russian-\u003elength();      // 12 (character count)\necho $russian-\u003egetBytes();    // More than 12 (byte count)\n\n// Character access\necho $russian-\u003echarAt(0);     // \"П\"\necho $chinese-\u003echarAt(0);     // \"你\"\n\n// Substring extraction\necho $russian-\u003esubstring(0, 6);  // \"Привет\"\necho $chinese-\u003esubstring(0, 2);  // \"你好\"\n\n// Case conversion (where applicable)\necho $russian-\u003etoUpperCase();    // \"ПРИВЕТ, МИР!\"\necho $russian-\u003etoLowerCase();    // \"привет, мир!\"\n```\n\n### Text Transformation\n\n```php\n// Reverse (correctly handles multibyte)\necho $russian-\u003ereverse();     // \"!рим ,тевирП\"\n\n// Replace\necho $russian-\u003ereplace('мир', 'свет');  // \"Привет, свет!\"\n\n// Trim\necho Str::from('  Привет  ')-\u003etrim();  // \"Привет\"\n\n// Character iterations\n$iterator = $russian-\u003egetIterator();\nforeach ($iterator as $char) {\n    echo $char . ' ';  // \"П р и в е т ,   м и р !\"\n}\n```\n\n### Array Access with Multibyte\n\n```php\n$mutable = StrMutable::create('Привет');\necho $mutable[0];      // \"П\"\n\n$mutable[0] = 'К';\necho $mutable;         // \"Кривет\"\n\nunset($mutable[5]);\necho $mutable;         // \"Криве\"\n```\n\n### Working with Different Scripts\n\n```php\n// Japanese\n$japanese = Str::from('こんにちは世界', 'UTF-8');\necho $japanese-\u003elength();        // 7 characters\necho $japanese-\u003esubstring(0, 5); // \"こんにちは\"\n\n// Thai (with combining diacritical marks)\n$thai = Str::from('สวัสดีโลก', 'UTF-8');\necho $thai-\u003elength();            // Correctly counts Thai characters with marks\n\n// Emoji\n$emoji = Str::from('Hello 👋 World 🌍', 'UTF-8');\necho $emoji-\u003elength();           // Correctly counts emoji characters\necho $emoji-\u003esubstring(6, 1);    // \"👋\"\n\n// Mixed script text\n$mixed = Str::from('Hello Привет 你好 مرحبا', 'UTF-8');\nforeach ($mixed-\u003ewords() as $word) {\n    echo $word . \"\\n\";  // Correctly splits words across scripts\n}\n```\n\n## License\n\nThis library is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please create a pull request on the GitHub repository.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbermudaphp%2Fstringy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbermudaphp%2Fstringy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbermudaphp%2Fstringy/lists"}