File indexing completed on 2025-01-26 05:29:58
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Stdlib 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 */ 0020 0021 // require_once 'Zend/Stdlib/SplPriorityQueue.php'; 0022 0023 /** 0024 * Re-usable, serializable priority queue implementation 0025 * 0026 * SplPriorityQueue acts as a heap; on iteration, each item is removed from the 0027 * queue. If you wish to re-use such a queue, you need to clone it first. This 0028 * makes for some interesting issues if you wish to delete items from the queue, 0029 * or, as already stated, iterate over it multiple times. 0030 * 0031 * This class aggregates items for the queue itself, but also composes an 0032 * "inner" iterator in the form of an SplPriorityQueue object for performing 0033 * the actual iteration. 0034 * 0035 * @category Zend 0036 * @package Zend_Stdlib 0037 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0038 * @license http://framework.zend.com/license/new-bsd New BSD License 0039 */ 0040 class Zend_Stdlib_PriorityQueue implements Countable, IteratorAggregate, Serializable 0041 { 0042 const EXTR_DATA = 0x00000001; 0043 const EXTR_PRIORITY = 0x00000002; 0044 const EXTR_BOTH = 0x00000003; 0045 0046 /** 0047 * Inner queue class to use for iteration 0048 * @var string 0049 */ 0050 protected $queueClass = 'Zend_Stdlib_SplPriorityQueue'; 0051 0052 /** 0053 * Actual items aggregated in the priority queue. Each item is an array 0054 * with keys "data" and "priority". 0055 * @var array 0056 */ 0057 protected $items = array(); 0058 0059 /** 0060 * Inner queue object 0061 * @var SplPriorityQueue 0062 */ 0063 protected $queue; 0064 0065 /** 0066 * Insert an item into the queue 0067 * 0068 * Priority defaults to 1 (low priority) if none provided. 0069 * 0070 * @param mixed $data 0071 * @param int $priority 0072 * @return Zend_Stdlib_PriorityQueue 0073 */ 0074 public function insert($data, $priority = 1) 0075 { 0076 $priority = (int) $priority; 0077 $this->items[] = array( 0078 'data' => $data, 0079 'priority' => $priority, 0080 ); 0081 $this->getQueue()->insert($data, $priority); 0082 return $this; 0083 } 0084 0085 /** 0086 * Remove an item from the queue 0087 * 0088 * This is different than {@link extract()}; its purpose is to dequeue an 0089 * item. 0090 * 0091 * This operation is potentially expensive, as it requires 0092 * re-initialization and re-population of the inner queue. 0093 * 0094 * Note: this removes the first item matching the provided item found. If 0095 * the same item has been added multiple times, it will not remove other 0096 * instances. 0097 * 0098 * @param mixed $datum 0099 * @return boolean False if the item was not found, true otherwise. 0100 */ 0101 public function remove($datum) 0102 { 0103 $found = false; 0104 foreach ($this->items as $key => $item) { 0105 if ($item['data'] === $datum) { 0106 $found = true; 0107 break; 0108 } 0109 } 0110 if ($found) { 0111 unset($this->items[$key]); 0112 $this->queue = null; 0113 $queue = $this->getQueue(); 0114 foreach ($this->items as $item) { 0115 $queue->insert($item['data'], $item['priority']); 0116 } 0117 return true; 0118 } 0119 return false; 0120 } 0121 0122 /** 0123 * Is the queue empty? 0124 * 0125 * @return bool 0126 */ 0127 public function isEmpty() 0128 { 0129 return (0 === $this->count()); 0130 } 0131 0132 /** 0133 * How many items are in the queue? 0134 * 0135 * @return int 0136 */ 0137 public function count() 0138 { 0139 return count($this->items); 0140 } 0141 0142 /** 0143 * Peek at the top node in the queue, based on priority. 0144 * 0145 * @return mixed 0146 */ 0147 public function top() 0148 { 0149 return $this->getIterator()->top(); 0150 } 0151 0152 /** 0153 * Extract a node from the inner queue and sift up 0154 * 0155 * @return mixed 0156 */ 0157 public function extract() 0158 { 0159 return $this->getQueue()->extract(); 0160 } 0161 0162 /** 0163 * Retrieve the inner iterator 0164 * 0165 * SplPriorityQueue acts as a heap, which typically implies that as items 0166 * are iterated, they are also removed. This does not work for situations 0167 * where the queue may be iterated multiple times. As such, this class 0168 * aggregates the values, and also injects an SplPriorityQueue. This method 0169 * retrieves the inner queue object, and clones it for purposes of 0170 * iteration. 0171 * 0172 * @return SplPriorityQueue 0173 */ 0174 public function getIterator() 0175 { 0176 $queue = $this->getQueue(); 0177 return clone $queue; 0178 } 0179 0180 /** 0181 * Serialize the data structure 0182 * 0183 * @return string 0184 */ 0185 public function serialize() 0186 { 0187 return serialize($this->items); 0188 } 0189 0190 /** 0191 * Unserialize a string into a Zend_Stdlib_PriorityQueue object 0192 * 0193 * Serialization format is compatible with {@link Zend_Stdlib_SplPriorityQueue} 0194 * 0195 * @param string $data 0196 * @return void 0197 */ 0198 public function unserialize($data) 0199 { 0200 foreach (unserialize($data) as $item) { 0201 $this->insert($item['data'], $item['priority']); 0202 } 0203 } 0204 0205 /** 0206 * Serialize to an array 0207 * 0208 * By default, returns only the item data, and in the order registered (not 0209 * sorted). You may provide one of the EXTR_* flags as an argument, allowing 0210 * the ability to return priorities or both data and priority. 0211 * 0212 * @param int $flag 0213 * @return array 0214 */ 0215 public function toArray($flag = self::EXTR_DATA) 0216 { 0217 switch ($flag) { 0218 case self::EXTR_BOTH: 0219 return $this->items; 0220 case self::EXTR_PRIORITY: 0221 return array_map(array($this, 'returnPriority'), $this->items); 0222 case self::EXTR_DATA: 0223 default: 0224 return array_map(array($this, 'returnData'), $this->items); 0225 } 0226 } 0227 0228 /** 0229 * Specify the internal queue class 0230 * 0231 * Please see {@link getIterator()} for details on the necessity of an 0232 * internal queue class. The class provided should extend SplPriorityQueue. 0233 * 0234 * @param string $class 0235 * @return Zend_Stdlib_PriorityQueue 0236 */ 0237 public function setInternalQueueClass($class) 0238 { 0239 $this->queueClass = (string) $class; 0240 return $this; 0241 } 0242 0243 /** 0244 * Does the queue contain the given datum? 0245 * 0246 * @param mixed $datum 0247 * @return bool 0248 */ 0249 public function contains($datum) 0250 { 0251 foreach ($this->items as $item) { 0252 if ($item['data'] === $datum) { 0253 return true; 0254 } 0255 } 0256 return false; 0257 } 0258 0259 /** 0260 * Does the queue have an item with the given priority? 0261 * 0262 * @param int $priority 0263 * @return bool 0264 */ 0265 public function hasPriority($priority) 0266 { 0267 foreach ($this->items as $item) { 0268 if ($item['priority'] === $priority) { 0269 return true; 0270 } 0271 } 0272 return false; 0273 } 0274 0275 /** 0276 * Get the inner priority queue instance 0277 * 0278 * @return Zend_Stdlib_SplPriorityQueue 0279 */ 0280 protected function getQueue() 0281 { 0282 if (null === $this->queue) { 0283 $this->queue = new $this->queueClass(); 0284 if (!$this->queue instanceof SplPriorityQueue) { 0285 throw new DomainException(sprintf( 0286 'Zend_Stdlib_PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"', 0287 get_class($this->queue) 0288 )); 0289 } 0290 } 0291 return $this->queue; 0292 } 0293 0294 /** 0295 * Return priority from an internal item 0296 * 0297 * Used as a lambda in toArray(). 0298 * 0299 * @param array $item 0300 * @return mixed 0301 */ 0302 public function returnPriority($item) 0303 { 0304 return $item['priority']; 0305 } 0306 0307 /** 0308 * Return data from an internal item 0309 * 0310 * Used as a lambda in toArray(). 0311 * 0312 * @param array $item 0313 * @return mixed 0314 */ 0315 public function returnData($item) 0316 { 0317 return $item['data']; 0318 } 0319 }