PageRenderTime 47ms CodeModel.GetById 36ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/vendor/swift/lib/classes/Swift/StreamFilters/ByteArrayReplacementFilter.php

http://zoop.googlecode.com/
PHP | 188 lines | 127 code | 17 blank | 44 comment | 18 complexity | 02ff52ee82e189189a8371460584c513 MD5 | raw file
  1<?php
  2
  3/*
  4 * This file is part of SwiftMailer.
  5 * (c) 2004-2009 Chris Corbyn
  6 *
  7 * For the full copyright and license information, please view the LICENSE
  8 * file that was distributed with this source code.
  9 */
 10
 11//@require 'Swift/StreamFilter.php';
 12
 13/**
 14 * Processes bytes as they pass through a buffer and replaces sequences in it.
 15 * This stream filter deals with Byte arrays rather than simple strings.
 16 * @package Swift
 17 * @author Chris Corbyn
 18 */
 19class Swift_StreamFilters_ByteArrayReplacementFilter
 20  implements Swift_StreamFilter
 21{
 22
 23  /** The needle(s) to search for */
 24  private $_search;
 25
 26  /** The replacement(s) to make */
 27  private $_replace;
 28
 29  /** The Index for searching */
 30  private $_index;
 31
 32  /** The Search Tree */
 33  private $_tree = array();
 34
 35  /**  Gives the size of the largest search */
 36  private $_treeMaxLen = 0;
 37  
 38  private $_repSize;
 39
 40  /**
 41   * Create a new ByteArrayReplacementFilter with $search and $replace.
 42   * @param array $search
 43   * @param array $replace
 44   */
 45  public function __construct($search, $replace)
 46  {
 47    $this->_search = $search;
 48    $this->_index = array();
 49    $this->_tree = array();
 50    $this->_replace = array();
 51    $this->_repSize = array();
 52    
 53    $tree = null;
 54    $i = null;
 55    $last_size = $size = 0;
 56    foreach ($search as $i => $search_element)
 57    {
 58      if ($tree !== null)
 59      {
 60        $tree[-1] = min (count($replace) - 1, $i - 1);
 61        $tree[-2] = $last_size;
 62      }
 63      $tree = &$this->_tree;
 64      if (is_array ($search_element))
 65      {
 66        foreach ($search_element as $k => $char)
 67        {
 68          $this->_index[$char] = true;
 69          if (!isset($tree[$char]))
 70          {
 71            $tree[$char] = array();
 72          }
 73          $tree = &$tree[$char];
 74        }
 75        $last_size = $k+1;
 76        $size = max($size, $last_size);
 77      }
 78      else
 79      {
 80        $last_size = 1;
 81        if (!isset($tree[$search_element]))
 82        {
 83          $tree[$search_element] = array();
 84        }
 85        $tree = &$tree[$search_element];
 86        $size = max($last_size, $size);
 87        $this->_index[$search_element] = true;
 88      }
 89    }
 90    if ($i !== null)
 91    {
 92      $tree[-1] = min (count ($replace) - 1, $i);
 93      $tree[-2] = $last_size;
 94      $this->_treeMaxLen = $size;
 95    }
 96    foreach ($replace as $rep)
 97    {
 98      if (!is_array($rep))
 99      {
100        $rep = array ($rep);
101      }
102      $this->_replace[] = $rep;
103    }
104    for ($i = count($this->_replace) - 1; $i >= 0; --$i)
105    {
106      $this->_replace[$i] = $rep = $this->filter($this->_replace[$i], $i);
107      $this->_repSize[$i] = count($rep);
108    }
109  }
110
111  /**
112   * Returns true if based on the buffer passed more bytes should be buffered.
113   * @param array $buffer
114   * @return boolean
115   */
116  public function shouldBuffer($buffer)
117  {
118    $endOfBuffer = end($buffer);
119    return isset ($this->_index[$endOfBuffer]);
120  }
121
122  /**
123   * Perform the actual replacements on $buffer and return the result.
124   * @param array $buffer
125   * @return array
126   */
127  public function filter($buffer, $_minReplaces = -1)
128  {
129    if ($this->_treeMaxLen == 0)
130    {
131      return $buffer;
132    }
133    
134    $newBuffer = array();
135    $buf_size = count($buffer);
136    for ($i = 0; $i < $buf_size; ++$i)
137    {
138      $search_pos = $this->_tree;
139      $last_found = PHP_INT_MAX;
140      // We try to find if the next byte is part of a search pattern
141      for ($j = 0; $j <= $this->_treeMaxLen; ++$j)
142      {
143        // We have a new byte for a search pattern
144        if (isset ($buffer [$p = $i + $j]) && isset($search_pos[$buffer[$p]]))
145        {
146          $search_pos = $search_pos[$buffer[$p]];
147          // We have a complete pattern, save, in case we don't find a better match later
148          if (isset($search_pos[- 1]) && $search_pos[-1] < $last_found
149            && $search_pos[-1] > $_minReplaces)
150          {
151            $last_found = $search_pos[-1];
152            $last_size = $search_pos[-2];
153          }
154        }
155        // We got a complete pattern
156        elseif ($last_found !== PHP_INT_MAX)
157        {
158          // Adding replacement datas to output buffer
159          $rep_size = $this->_repSize[$last_found];
160          for ($j = 0; $j < $rep_size; ++$j)
161          {
162            $newBuffer[] = $this->_replace[$last_found][$j];
163          }
164          // We Move cursor forward
165          $i += $last_size - 1;
166          // Edge Case, last position in buffer
167          if ($i >= $buf_size)
168          {
169            $newBuffer[] = $buffer[$i];
170          }
171          
172          // We start the next loop
173          continue 2;
174        }
175        else
176        {
177          // this byte is not in a pattern and we haven't found another pattern
178          break;
179        }
180      }
181      // Normal byte, move it to output buffer
182      $newBuffer[] = $buffer[$i];
183    }
184    
185    return $newBuffer;
186  }
187
188}