Skip to content

Commit

Permalink
[mms] Add the Horde_Stream_String class.
Browse files Browse the repository at this point in the history
  • Loading branch information
slusarz committed Jan 29, 2014
1 parent 6e785a4 commit d53c996
Show file tree
Hide file tree
Showing 12 changed files with 869 additions and 255 deletions.
32 changes: 23 additions & 9 deletions framework/Stream/lib/Horde/Stream.php
Expand Up @@ -22,18 +22,11 @@
* @package Stream
*
* @property-read resource $stream Stream resource (@deprecated).
* @property boolean $utf8_char Parse character as UTF-8 data instead of
* single byte (@since 1.4.0).
*/
class Horde_Stream implements Serializable
{
/**
* Parse character as UTF-8 data instead of single byte.
*
* @since 1.4.0
*
* @var boolean
*/
public $utf8_char = false;

/**
* Configuration parameters.
*
Expand All @@ -50,6 +43,13 @@ class Horde_Stream implements Serializable
*/
protected $_stream;

/**
* Parse character as UTF-8 data instead of single byte.
*
* @var boolean
*/
protected $_utf8_char = false;

/**
* Constructor.
*
Expand Down Expand Up @@ -79,6 +79,20 @@ public function __get($name)
switch ($name) {
case 'stream':
return $this->_stream;

case 'utf8_char':
return $this->_utf8_char;
}
}

/**
*/
public function __set($name, $value)
{
switch ($name) {
case 'utf8_char':
$this->_utf8_char = (bool)$value;
break;
}
}

Expand Down
308 changes: 308 additions & 0 deletions framework/Stream/lib/Horde/Stream/String.php
@@ -0,0 +1,308 @@
<?php
/**
* Copyright 2014 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Stream
*/

/**
* Implementation of Horde_Stream that uses a PHP native string variable
* for the internal storage.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Stream
* @since 1.6.0
*/
class Horde_Stream_String extends Horde_Stream
{
/**
* Current string pointer.
*
* @var integer
*/
protected $_ptr = 0;

/**
* String data.
*
* @var string
*/
protected $_str = '';

/**
*/
protected function _init()
{
/* Don't initialize stream by default. */
}

/**
*/
public function __get($name)
{
switch ($name) {
case 'stream':
$stream = new Horde_Support_StringStream($this->_str);
return $stream->fopen();
}

return parent::__get($name);
}

/**
*/
public function __clone()
{
/* Overrides parent class. */
}

/**
*/
public function __toString()
{
return $this->_str;
}

/**
*/
public function add($data, $reset = false)
{
if (!is_string($data)) {
return parent::add($data, $reset);
}

if ($this->_ptr === (strlen($this->_str) - 1)) {
$this->_str .= $data;
} else {
$this->_str = substr_replace(
$this->_str,
$data,
$this->_ptr,
strlen($data)
);
}

if (!$reset) {
$this->_ptr += strlen($data);
}
}

/**
*/
public function length($utf8 = false)
{
return ($utf8 && $this->utf8_char)
? Horde_String::length($this->_str)
: strlen($this->_str);
}

/**
*/
public function peek($length = 1)
{
return $this->utf8_char
? Horde_String::substr($this->_str, $this->_posUtf8(), $length)
: substr($this->_str, $this->_ptr, $length);
}

/**
*/
public function search($char, $reverse = false, $reset = true)
{
$char = strval($char);
if (!strlen($char)) {
return null;
}

$pos = $this->pos();

if ($this->utf8_char) {
$found_pos = $reverse
? Horde_String::rpos($this->_str, $char, $this->length(true) - $this->_posUtf8())
: Horde_String::pos($this->_str, $char, $this->_posUtf8());
if ($found_pos) {
$found_pos = $this->_posUtf8($found_pos);
}
} else {
$found_pos = $reverse
? strrpos($this->_str, $char, $this->length() - $pos)
: strpos($this->_str, $char, $pos);
}

$this->seek(
($reset || ($found_pos === false)) ? $pos : $found_pos,
false
);

return ($found_pos === false)
? null
: $found_pos;
}

/**
*/
public function substring($start = 0, $length = null, $char = false)
{
if ($start !== 0) {
$this->seek($start, true, $char);
}

if ($this->eof()) {
return '';
}

if (is_null($length)) {
$out = substr($this->_str, $this->_ptr);
$this->end();
return $out;
}

$out = $char
? Horde_String::substr($this->_str, $this->_posUtf8(), $length)
: substr($this->_str, $this->_ptr, $length);
$this->seek(max($length, strlen($out)));

return $out;
}

/**
*/
public function getChar()
{
$char = $this->peek();

if ($len = strlen($char)) {
$this->seek($len);
} else {
$this->_ptr = false;
}

return $char;
}

/**
*/
public function pos()
{
return $this->_ptr;
}

/**
* Determines the current UTF-8 aware position in the stream.
*
* @param integer $utf8 If set, will convert from utf8 position to
* byte position.
*
* @return integer Position.
*/
protected function _posUtf8($utf8 = null)
{
return is_null($utf8)
? Horde_String::length(substr($this->_str, 0, $this->_ptr))
: strlen(Horde_String::substr($this->_str, 0, $utf8));
}

/**
*/
public function rewind()
{
$this->_ptr = 0;
return true;
}

/**
*/
public function seek($offset = 0, $curr = true, $char = false)
{
if (!$offset) {
return (bool)$curr ?: $this->rewind();
}

/* Optimizations if offset is negative. */
if ($offset < 0) {
if (!$curr) {
return true;
} elseif (abs($offset) > $this->_ptr) {
return $this->rewind();
}
}

if ($char) {
if ($curr) {
if ($offset > 0) {
$this->substring(0, $offset, true);
} else {
while (--$this->_ptr && ($offset < 0)) {
$offset += strlen(Horde_String::substr($this->_str, $this->_ptr, 1));
}
}
} else {
$this->_ptr = $this->_posUtf8($offset);
}
} elseif ($curr) {
$this->_ptr += $offset;
} else {
$this->_ptr = $offset;
}

if ($this->_ptr < 0) {
$this->_ptr = 0;
} elseif ($this->_ptr > $this->length()) {
$this->_ptr = false;
}

return true;
}

/**
*/
public function end($offset = 0)
{
$this->_ptr = $this->length();
if ($offset) {
$this->seek($offset, true, $this->utf8_char);
}

return true;
}

/**
*/
public function eof()
{
return ($this->_ptr === false);
}

/* Serializable methods. */

/**
*/
public function serialize()
{
return json_encode(array(
$this->_ptr,
$this->_str,
$this->_params
));
}

/**
*/
public function unserialize($data)
{
$data = json_decode($data, true);
$this->_ptr = $data[0];
$this->_str = $data[1];
$this->_params = $data[2];
}

}

0 comments on commit d53c996

Please sign in to comment.