Add Horde_Support_StringStream and the supporting Horde_Stream_Wrapper_String class
authorChuck Hagenbuch <chuck@horde.org>
Tue, 15 Sep 2009 02:45:27 +0000 (22:45 -0400)
committerChuck Hagenbuch <chuck@horde.org>
Tue, 15 Sep 2009 02:45:27 +0000 (22:45 -0400)
Provides a way to treat a string variable as a stream without duplicating it or
using global scope.

framework/Stream_Wrapper/lib/Horde/Stream/Wrapper/String.php [new file with mode: 0644]
framework/Stream_Wrapper/package.xml [new file with mode: 0644]
framework/Support/lib/Horde/Support/StringStream.php [new file with mode: 0644]
framework/Support/package.xml

diff --git a/framework/Stream_Wrapper/lib/Horde/Stream/Wrapper/String.php b/framework/Stream_Wrapper/lib/Horde/Stream/Wrapper/String.php
new file mode 100644 (file)
index 0000000..fba4b71
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @license  http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package  Horde_Stream_Wrapper
+ */
+
+/**
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @license  http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package  Horde_Stream_Wrapper
+ */
+class Horde_Stream_Wrapper_String
+{
+    /**
+     * @var resource
+     */
+    public $context;
+
+    /**
+     * @var string
+     */
+    protected $_string;
+
+    /**
+     * @var integer
+     */
+    protected $_length;
+
+    /**
+     * @var integer
+     */
+    protected $_position;
+
+    /**
+     * @param string $path
+     * @param string $mode
+     * @param integer $options
+     * @param string &$opened_path
+     */
+    public function stream_open($path, $mode, $options, &$opened_path)
+    {
+        $options = stream_context_get_options($this->context);
+        if (empty($options['horde-string']['string']) || ! $options['horde-string']['string'] instanceof Horde_Support_StringStream) {
+            throw new Exception('String streams must be created using the Horde_Stream_Wrapper_String_Factory class');
+        }
+
+        $this->_string =& $options['horde-string']['string']->getString();
+        if (is_null($this->_string)) {
+            return false;
+        }
+
+        $this->_length = strlen($this->_string);
+        $this->_position = 0;
+        return true;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function stream_stat()
+    {
+        return false;
+    }
+
+    /**
+     * @param integer $count
+     *
+     * @return string
+     */
+    public function stream_read($count)
+    {
+        $current = $this->_position;
+        $this->_position += $count;
+        return substr($this->_string, $current, $count);
+    }
+
+    /**
+     * @param string $data
+     *
+     * @return integer
+     */
+    public function stream_write($data)
+    {
+        return strlen($data);
+    }
+
+    /**
+     * @return integer
+     */
+    public function stream_tell()
+    {
+        return $this->_position;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function stream_eof()
+    {
+        return ($this->_position > $this->_length);
+    }
+
+    /**
+     * @param integer $offset
+     * @param integer $whence SEEK_SET, SEEK_CUR, or SEEK_END
+     */
+    public function stream_seek($offset, $whence)
+    {
+        if ($offset > $this->_length) {
+            return false;
+        }
+
+        switch ($whence) {
+        case SEEK_SET:
+            $this->_position = $offset;
+            break;
+
+        case SEEK_CUR:
+            $target = $this->_position + $offset;
+            if ($target < $this->_length) {
+                $this->_position = $target;
+            } else {
+                return false;
+            }
+            break;
+
+        case SEEK_END:
+            $this->_position = $this->_length - $offset;
+            break;
+        }
+
+        return true;
+    }
+}
diff --git a/framework/Stream_Wrapper/package.xml b/framework/Stream_Wrapper/package.xml
new file mode 100644 (file)
index 0000000..9a4de92
--- /dev/null
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Stream_Wrapper</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Stream filters</summary>
+ <description>This package provides various stream filters.
+ </description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Jan Schneider</name>
+  <user>jan</user>
+  <email>jan@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Michael Slusarz</name>
+  <user>slusarz</user>
+  <email>slusarz@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2009-07-08</date>
+ <version>
+  <release>0.1.0</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Initial release.
+ </notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Stream">
+      <dir name="Wrapper">
+       <file name="String.php" role="php" />
+      </dir> <!-- /lib/Horde/Stream/Wrapper -->
+     </dir> <!-- /lib/Horde/Stream -->
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.7.0</min>
+   </pearinstaller>
+  </required>
+  <optional/>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Stream/Wrapper/String.php" as="Horde/Stream/Wrapper/String.php" />
+  </filelist>
+ </phprelease>
+</package>
diff --git a/framework/Support/lib/Horde/Support/StringStream.php b/framework/Support/lib/Horde/Support/StringStream.php
new file mode 100644 (file)
index 0000000..a4927df
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Copyright 2007-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @license  http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package  Horde_Support
+ */
+
+/**
+ * @author   Chuck Hagenbuch <chuck@horde.org>
+ * @license  http://opensource.org/licenses/bsd-license.php BSD
+ * @category Horde
+ * @package  Horde_Support
+ */
+class Horde_Support_StringStream
+{
+    /**
+     * @var string
+     */
+    protected $_string;
+
+    /**
+     * Constructor
+     *
+     * @param string &$string  Reference to the string to wrap as a stream
+     */
+    public function __construct(&$string)
+    {
+        $this->installWrapper();
+        $this->_string =& $string;
+    }
+
+    /**
+     * Return a stream handle to this string stream.
+     *
+     * @return resource
+     */
+    public function fopen()
+    {
+        $context = stream_context_create(array('horde-string' => array('string' => $this)));
+        return fopen('horde-string://' . spl_object_hash($this), 'rb', false, $context);
+    }
+
+    /**
+     * Install the horde-string stream wrapper if it isn't already registered.
+     */
+    public function installWrapper()
+    {
+        if (!in_array('horde-string', stream_get_wrappers())) {
+            if (!stream_wrapper_register('horde-string', 'Horde_Stream_Wrapper_String')) {
+                throw new Exception('Unable to register horde-string stream wrapper');
+            }
+        }
+    }
+
+    /**
+     * Return a reference to the wrapped string.
+     *
+     * @return string
+     */
+    public function &getString()
+    {
+        return $this->_string;
+    }
+}
index d882740..befa480 100644 (file)
@@ -30,6 +30,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
    * Initial Horde_Support_ConsistentHash object
    * Initial Horde_Support_Inflector object
    * Initial Horde_Support_Stack object
+   * Initial Horde_Support_StringStream object
    * Initial Horde_Support_Stub object
    * Initial Horde_Support_Timer object
    * Initial Horde_Support_Uuid object
@@ -51,6 +52,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
       <file name="Inflector.php" role="php" />
       <file name="Numerizer.php" role="php" />
       <file name="Stack.php" role="php" />
+      <file name="StringStream.php" role="php" />
       <file name="Stub.php" role="php" />
       <file name="Timer.php" role="php" />
       <file name="Uuid.php" role="php" />
@@ -68,6 +70,12 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <min>1.5.0</min>
    </pearinstaller>
   </required>
+  <optional>
+   <package>
+    <name>Stream_Wrapper</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </optional>
  </dependencies>
  <phprelease>
   <filelist>
@@ -78,6 +86,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
    <install name="lib/Horde/Support/Numerizer/Locale/De.php" as="Horde/Support/Numerizer/Locale/De.php" />
    <install name="lib/Horde/Support/Numerizer.php" as="Horde/Support/Numerizer.php" />
    <install name="lib/Horde/Support/Stack.php" as="Horde/Support/Stack.php" />
+   <install name="lib/Horde/Support/StringStream.php" as="Horde/Support/StringStream.php" />
    <install name="lib/Horde/Support/Stub.php" as="Horde/Support/Stub.php" />
    <install name="lib/Horde/Support/Timer.php" as="Horde/Support/Timer.php" />
    <install name="lib/Horde/Support/Uuid.php" as="Horde/Support/Uuid.php" />