vendor/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php
changeset 0 7f95f8617b0b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/swiftmailer/lib/classes/Swift/CharacterStream/ArrayCharacterStream.php	Sat Sep 24 15:40:41 2011 +0200
@@ -0,0 +1,317 @@
+<?php
+
+/*
+ * This file is part of SwiftMailer.
+ * (c) 2004-2009 Chris Corbyn
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+
+
+/**
+ * A CharacterStream implementation which stores characters in an internal array.
+ * @package Swift
+ * @subpackage CharacterStream
+ * @author Chris Corbyn
+ */
+class Swift_CharacterStream_ArrayCharacterStream
+  implements Swift_CharacterStream
+{
+  
+  /** A map of byte values and their respective characters */
+  private static $_charMap;
+  
+  /** A map of characters and their derivative byte values */
+  private static $_byteMap;
+  
+  /** The char reader (lazy-loaded) for the current charset */
+  private $_charReader;
+
+  /** A factory for creatiing CharacterReader instances */
+  private $_charReaderFactory;
+
+  /** The character set this stream is using */
+  private $_charset;
+
+  /** Array of characters */
+  private $_array = array();
+
+  /** Size of the array of character */
+  private $_array_size = array();
+
+  /** The current character offset in the stream */
+  private $_offset = 0;
+
+  /**
+   * Create a new CharacterStream with the given $chars, if set.
+   * @param Swift_CharacterReaderFactory $factory for loading validators
+   * @param string $charset used in the stream
+   */
+  public function __construct(Swift_CharacterReaderFactory $factory,
+    $charset)
+  {
+    self::_initializeMaps();
+    $this->setCharacterReaderFactory($factory);
+    $this->setCharacterSet($charset);
+  }
+
+  /**
+   * Set the character set used in this CharacterStream.
+   * @param string $charset
+   */
+  public function setCharacterSet($charset)
+  {
+    $this->_charset = $charset;
+    $this->_charReader = null;
+  }
+
+  /**
+   * Set the CharacterReaderFactory for multi charset support.
+   * @param Swift_CharacterReaderFactory $factory
+   */
+  public function setCharacterReaderFactory(
+    Swift_CharacterReaderFactory $factory)
+  {
+    $this->_charReaderFactory = $factory;
+  }
+
+  /**
+   * Overwrite this character stream using the byte sequence in the byte stream.
+   * @param Swift_OutputByteStream $os output stream to read from
+   */
+  public function importByteStream(Swift_OutputByteStream $os)
+  {
+    if (!isset($this->_charReader))
+    {
+      $this->_charReader = $this->_charReaderFactory
+        ->getReaderFor($this->_charset);
+    }
+
+    $startLength = $this->_charReader->getInitialByteSize();
+    while (false !== $bytes = $os->read($startLength))
+    {
+      $c = array();
+      for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
+      {
+        $c[] = self::$_byteMap[$bytes[$i]];
+      }
+      $size = count($c);
+      $need = $this->_charReader
+        ->validateByteSequence($c, $size);
+      if ($need > 0 &&
+        false !== $bytes = $os->read($need))
+      {
+        for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
+        {
+          $c[] = self::$_byteMap[$bytes[$i]];
+        }
+      }
+      $this->_array[] = $c;
+      ++$this->_array_size;
+    }
+  }
+
+  /**
+   * Import a string a bytes into this CharacterStream, overwriting any existing
+   * data in the stream.
+   * @param string $string
+   */
+  public function importString($string)
+  {
+    $this->flushContents();
+    $this->write($string);
+  }
+
+  /**
+   * Read $length characters from the stream and move the internal pointer
+   * $length further into the stream.
+   * @param int $length
+   * @return string
+   */
+  public function read($length)
+  {
+    if ($this->_offset == $this->_array_size)
+    {
+      return false;
+    }
+
+    // Don't use array slice
+    $arrays = array();
+    $end = $length + $this->_offset;
+    for ($i = $this->_offset; $i < $end; ++$i)
+    {
+      if (!isset($this->_array[$i]))
+      {
+        break;
+      }
+      $arrays[] = $this->_array[$i];
+    }
+    $this->_offset += $i - $this->_offset; // Limit function calls
+    $chars = false;
+    foreach ($arrays as $array)
+    {
+      $chars .= implode('', array_map('chr', $array));
+    }
+    return $chars;
+  }
+
+  /**
+   * Read $length characters from the stream and return a 1-dimensional array
+   * containing there octet values.
+   * @param int $length
+   * @return int[]
+   */
+  public function readBytes($length)
+  {
+    if ($this->_offset == $this->_array_size)
+    {
+      return false;
+    }
+    $arrays = array();
+    $end = $length + $this->_offset;
+    for ($i = $this->_offset; $i < $end; ++$i)
+    {
+      if (!isset($this->_array[$i]))
+      {
+        break;
+      }
+      $arrays[] = $this->_array[$i];
+    }
+    $this->_offset += ($i - $this->_offset); // Limit function calls
+    return call_user_func_array('array_merge', $arrays);
+  }
+
+  /**
+   * Write $chars to the end of the stream.
+   * @param string $chars
+   */
+  public function write($chars)
+  {
+    if (!isset($this->_charReader))
+    {
+      $this->_charReader = $this->_charReaderFactory->getReaderFor(
+        $this->_charset);
+    }
+
+    $startLength = $this->_charReader->getInitialByteSize();
+
+    $fp = fopen('php://memory', 'w+b');
+    fwrite($fp, $chars);
+    unset($chars);
+    fseek($fp, 0, SEEK_SET);
+
+    $buffer = array(0);
+    $buf_pos = 1;
+    $buf_len = 1;
+    $has_datas = true;
+    do
+    {
+      $bytes = array();
+      // Buffer Filing
+      if ($buf_len - $buf_pos < $startLength)
+      {
+        $buf = array_splice($buffer, $buf_pos);
+        $new = $this->_reloadBuffer($fp, 100);
+        if ($new)
+        {
+          $buffer = array_merge($buf, $new);
+          $buf_len = count($buffer);
+          $buf_pos = 0;
+        }
+        else
+        {
+          $has_datas = false;
+        }
+      }
+      if ($buf_len - $buf_pos > 0)
+      {
+        $size = 0;
+        for ($i = 0; $i < $startLength && isset($buffer[$buf_pos]); ++$i)
+        {
+          ++$size;
+          $bytes[] = $buffer[$buf_pos++];
+        }
+        $need = $this->_charReader->validateByteSequence(
+          $bytes, $size);
+        if ($need > 0)
+        {
+          if ($buf_len - $buf_pos < $need)
+          {
+            $new = $this->_reloadBuffer($fp, $need);
+            
+            if ($new)
+            {
+              $buffer = array_merge($buffer, $new);
+              $buf_len = count($buffer);
+            }
+          }
+          for ($i = 0; $i < $need && isset($buffer[$buf_pos]); ++$i)
+          {
+            $bytes[] = $buffer[$buf_pos++];
+          }
+        }
+        $this->_array[] = $bytes;
+        ++$this->_array_size;
+      }
+    }
+    while ($has_datas);
+    
+    fclose($fp);
+  }
+
+  /**
+   * Move the internal pointer to $charOffset in the stream.
+   * @param int $charOffset
+   */
+  public function setPointer($charOffset)
+  {
+    if ($charOffset > $this->_array_size)
+    {
+      $charOffset = $this->_array_size;
+    }
+    elseif ($charOffset < 0)
+    {
+      $charOffset = 0;
+    }
+    $this->_offset = $charOffset;
+  }
+
+  /**
+   * Empty the stream and reset the internal pointer.
+   */
+  public function flushContents()
+  {
+    $this->_offset = 0;
+    $this->_array = array();
+    $this->_array_size = 0;
+  }
+  
+  private function _reloadBuffer($fp, $len)
+  {
+    if (!feof($fp) && ($bytes = fread($fp, $len)) !== false)
+    {
+      $buf = array();
+      for ($i = 0, $len = strlen($bytes); $i < $len; ++$i)
+      {
+        $buf[] = self::$_byteMap[$bytes[$i]];
+      }
+      return $buf;
+    }
+    return false;
+  }
+  
+  private static function _initializeMaps()
+  {
+    if (!isset(self::$_charMap))
+    {
+      self::$_charMap = array();
+      for ($byte = 0; $byte < 256; ++$byte)
+      {
+        self::$_charMap[$byte] = chr($byte);
+      }
+      self::$_byteMap = array_flip(self::$_charMap);
+    }
+  }
+}