Created
November 27, 2013 20:29
-
-
Save nathggns/7682673 to your computer and use it in GitHub Desktop.
Class-representation of strings. Uses arrays internally.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Immutable String class that uses arrays to represent | |
* strings. | |
* | |
* Currently useless as we have no unicode friendly way to split a string | |
* into characters | |
* | |
* @todo Find a unicode-friendly way to split strings | |
* @todo Find a unicode-friendly way to convert case with characters | |
* @todo Add a way to find the length without exporting the string | |
*/ | |
class Str { | |
/** | |
* Store the array of characters | |
* @var array | |
*/ | |
private $characters; | |
/** | |
* Store the array of operations that we've had | |
* @var array | |
*/ | |
private $operations; | |
/** | |
* If we've computed our operations, store it here | |
* @var string | |
*/ | |
private $cached; | |
/** | |
* This function handles the creation of an Str instance | |
* @param array|string $chrs The string we'll represent. Can be a pre-split | |
* array of strings, or a native PHP string. | |
* @param array $operations An array of operations to start with. | |
* Mostly used internally. | |
*/ | |
public function __construct($chrs, $operations = []) { | |
// If we've been passed a string, split it | |
if (is_string($chrs)) { | |
// Would need a unicode-friendly way of splitting strings to | |
// make this class of absolutely any use | |
$chrs = str_split($chrs); | |
} | |
// Set some properties | |
$this->characters = $chrs; | |
$this->operations = $operations; | |
} | |
/** | |
* Simply a helper for a __construct | |
* | |
* @see __construct | |
*/ | |
public static function make($chrs, $operations = []) { | |
return new Str($chrs, $operations); | |
} | |
/** | |
* General purpose map operation. Call a function | |
* on each item in the array. | |
*/ | |
public function map($func) { | |
return $this->operation('map', [$func]); | |
} | |
/** | |
* General purpose operation to call a function on | |
* the array of characters. | |
*/ | |
public function func($func) { | |
return $this->operation('func', [$func]); | |
} | |
/** | |
* Reverse a string | |
*/ | |
public function reverse() { | |
return $this->func('array_reverse'); | |
} | |
/** | |
* Convert a string to uppercase | |
*/ | |
public function lower() { | |
return $this->map('strtolower'); | |
} | |
/** | |
* Convert a string to uppercase | |
*/ | |
public function upper() { | |
return $this->map('strtoupper'); | |
} | |
/** | |
* Export a string from the class | |
* @return string exported string | |
*/ | |
public function out() { | |
// If we've computed our operation before, | |
// use that instead. | |
if ($this->cached) { | |
return $this->cached; | |
} | |
// Create a local copy of the characters array | |
$chrs = $this->characters; | |
// Loop through each of the operations, applying each operation | |
// to our character set | |
foreach ($this->operations as $operation) { | |
$chrs = $this->handle_operation($chrs, $operation); | |
} | |
// Implode our character set to create the actual string | |
$this->cached = implode('', $chrs); | |
// Actually export the string | |
return $this->out(); | |
} | |
/** | |
* When converting this function to a string, we should | |
* just export the string. Simply an alias for out | |
* | |
* @see out | |
*/ | |
public function __toString() { | |
return $this->out(); | |
} | |
/** | |
* Private function to create a new instance of the Str | |
* class with a specific operation added to the stack. | |
* @param string $name The name of the operation | |
* @param array $args An array of arguments to pass to the operation handler | |
* @return Str A new instance of the str class | |
*/ | |
private function operation($name, $args = []) { | |
return new Str($this->characters, array_merge($this->operations, [(object) [ | |
'name' => $name, | |
'args' => $args | |
]])); | |
} | |
/** | |
* Private function that calls the correct operation handler | |
* @param array $chrs The array of characters | |
* @param object $operation An object representing the operation | |
* @return array Transformed characters | |
*/ | |
private function handle_operation($chrs, $operation) { | |
if (method_exists($this, '_' . $operation->name)) { | |
$chrs = call_user_func_array([$this, '_' . $operation->name], array_merge([$chrs, $operation->args])); | |
} else { | |
// @todo Might want to throw an exception here. My PHP isn't | |
// the best though. | |
} | |
return $chrs; | |
} | |
// From here, it's just the actual handlers for operations | |
private function _func($chrs, $args) { | |
return call_user_func($args[0], $chrs); | |
} | |
private function _map($chrs, $args) { | |
return array_map($args[0], $chrs); | |
} | |
} | |
var_dump(Str::make('ABC')->reverse()->lower()->out()); | |
// cba |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment