ok
Direktori : /home2/selectio/www/mm-tailor-billing/vendor/zendframework/zend-stdlib/src/ |
Current File : //home2/selectio/www/mm-tailor-billing/vendor/zendframework/zend-stdlib/src/FastPriorityQueue.php |
<?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Stdlib; use Iterator; use Countable; use Serializable; use SplPriorityQueue as PhpSplPriorityQueue; /** * This is an efficient implementation of an integer priority queue in PHP * * This class acts like a queue with insert() and extract(), removing the * elements from the queue and it also acts like an Iterator without removing * the elements. This behaviour can be used in mixed scenarios with high * performance boost. */ class FastPriorityQueue implements Iterator, Countable, Serializable { const EXTR_DATA = PhpSplPriorityQueue::EXTR_DATA; const EXTR_PRIORITY = PhpSplPriorityQueue::EXTR_PRIORITY; const EXTR_BOTH = PhpSplPriorityQueue::EXTR_BOTH; /** * @var integer */ protected $extractFlag = self::EXTR_DATA; /** * Elements of the queue, divided by priorities * * @var array */ protected $values = []; /** * Array of priorities * * @var array */ protected $priorities = []; /** * Array of priorities used for the iteration * * @var array */ protected $subPriorities = []; /** * Max priority * * @var integer|null */ protected $maxPriority = null; /** * Total number of elements in the queue * * @var integer */ protected $count = 0; /** * Index of the current element in the queue * * @var integer */ protected $index = 0; /** * Sub index of the current element in the same priority level * * @var integer */ protected $subIndex = 0; /** * Insert an element in the queue with a specified priority * * @param mixed $value * @param integer $priority */ public function insert($value, $priority) { if (! is_int($priority)) { throw new Exception\InvalidArgumentException('The priority must be an integer'); } $this->values[$priority][] = $value; if (! isset($this->priorities[$priority])) { $this->priorities[$priority] = $priority; $this->maxPriority = $this->maxPriority === null ? $priority : max($priority, $this->maxPriority); } ++$this->count; } /** * Extract an element in the queue according to the priority and the * order of insertion * * @return mixed */ public function extract() { if (! $this->valid()) { return false; } $value = $this->current(); $this->nextAndRemove(); return $value; } /** * Remove an item from the queue * * This is different than {@link extract()}; its purpose is to dequeue an * item. * * Note: this removes the first item matching the provided item found. If * the same item has been added multiple times, it will not remove other * instances. * * @param mixed $datum * @return bool False if the item was not found, true otherwise. */ public function remove($datum) { $currentIndex = $this->index; $currentSubIndex = $this->subIndex; $currentPriority = $this->maxPriority; $this->rewind(); while ($this->valid()) { if (current($this->values[$this->maxPriority]) === $datum) { $index = key($this->values[$this->maxPriority]); unset($this->values[$this->maxPriority][$index]); // The `next()` method advances the internal array pointer, so we need to use the `reset()` function, // otherwise we would lose all elements before the place the pointer points. reset($this->values[$this->maxPriority]); $this->index = $currentIndex; $this->subIndex = $currentSubIndex; // If the array is empty we need to destroy the unnecessary priority, // otherwise we would end up with an incorrect value of `$this->count` // {@see \Zend\Stdlib\FastPriorityQueue::nextAndRemove()}. if (empty($this->values[$this->maxPriority])) { unset($this->values[$this->maxPriority]); unset($this->priorities[$this->maxPriority]); if ($this->maxPriority === $currentPriority) { $this->subIndex = 0; } } $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); --$this->count; return true; } $this->next(); } return false; } /** * Get the total number of elements in the queue * * @return integer */ public function count() { return $this->count; } /** * Get the current element in the queue * * @return mixed */ public function current() { switch ($this->extractFlag) { case self::EXTR_DATA: return current($this->values[$this->maxPriority]); case self::EXTR_PRIORITY: return $this->maxPriority; case self::EXTR_BOTH: return [ 'data' => current($this->values[$this->maxPriority]), 'priority' => $this->maxPriority ]; } } /** * Get the index of the current element in the queue * * @return integer */ public function key() { return $this->index; } /** * Set the iterator pointer to the next element in the queue * removing the previous element */ protected function nextAndRemove() { $key = key($this->values[$this->maxPriority]); if (false === next($this->values[$this->maxPriority])) { unset($this->priorities[$this->maxPriority]); unset($this->values[$this->maxPriority]); $this->maxPriority = empty($this->priorities) ? null : max($this->priorities); $this->subIndex = -1; } else { unset($this->values[$this->maxPriority][$key]); } ++$this->index; ++$this->subIndex; --$this->count; } /** * Set the iterator pointer to the next element in the queue * without removing the previous element */ public function next() { if (false === next($this->values[$this->maxPriority])) { unset($this->subPriorities[$this->maxPriority]); reset($this->values[$this->maxPriority]); $this->maxPriority = empty($this->subPriorities) ? null : max($this->subPriorities); $this->subIndex = -1; } ++$this->index; ++$this->subIndex; } /** * Check if the current iterator is valid * * @return boolean */ public function valid() { return isset($this->values[$this->maxPriority]); } /** * Rewind the current iterator */ public function rewind() { $this->subPriorities = $this->priorities; $this->maxPriority = empty($this->priorities) ? 0 : max($this->priorities); $this->index = 0; $this->subIndex = 0; } /** * Serialize to an array * * Array will be priority => data pairs * * @return array */ public function toArray() { $array = []; foreach (clone $this as $item) { $array[] = $item; } return $array; } /** * Serialize * * @return string */ public function serialize() { $clone = clone $this; $clone->setExtractFlags(self::EXTR_BOTH); $data = []; foreach ($clone as $item) { $data[] = $item; } return serialize($data); } /** * Deserialize * * @param string $data * @return void */ public function unserialize($data) { foreach (unserialize($data) as $item) { $this->insert($item['data'], $item['priority']); } } /** * Set the extract flag * * @param integer $flag */ public function setExtractFlags($flag) { switch ($flag) { case self::EXTR_DATA: case self::EXTR_PRIORITY: case self::EXTR_BOTH: $this->extractFlag = $flag; break; default: throw new Exception\InvalidArgumentException("The extract flag specified is not valid"); } } /** * Check if the queue is empty * * @return boolean */ public function isEmpty() { return empty($this->values); } /** * Does the queue contain the given datum? * * @param mixed $datum * @return bool */ public function contains($datum) { foreach ($this->values as $values) { if (in_array($datum, $values)) { return true; } } return false; } /** * Does the queue have an item with the given priority? * * @param int $priority * @return bool */ public function hasPriority($priority) { return isset($this->values[$priority]); } }