Skip to content

Instantly share code, notes, and snippets.

@nathggns
Created November 27, 2013 20:29
Show Gist options
  • Save nathggns/7682673 to your computer and use it in GitHub Desktop.
Save nathggns/7682673 to your computer and use it in GitHub Desktop.
Class-representation of strings. Uses arrays internally.
<?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