Use SplDoublyLinkedList instead of custom linked list
parent
731a451dfe
commit
cdf3b4e012
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
|
*/
|
||||||
|
class RuleWatchChain extends \SplDoublyLinkedList
|
||||||
|
{
|
||||||
|
protected $offset = 0;
|
||||||
|
|
||||||
|
public function seek($offset)
|
||||||
|
{
|
||||||
|
$this->rewind();
|
||||||
|
for ($i = 0; $i < $offset; $i++, $this->next());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function remove()
|
||||||
|
{
|
||||||
|
$offset = $this->key();
|
||||||
|
$this->offsetUnset($offset);
|
||||||
|
$this->seek($offset);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,30 +22,20 @@ class RuleWatchGraph
|
||||||
/**
|
/**
|
||||||
* Alters watch chains for a rule.
|
* Alters watch chains for a rule.
|
||||||
*
|
*
|
||||||
* Next1/2 always points to the next rule that is watching the same package.
|
|
||||||
* The watches array contains rules to start from for each package
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public function insert(RuleWatchNode $node)
|
public function insert(RuleWatchNode $node)
|
||||||
{
|
{
|
||||||
// skip simple assertions of the form (A) or (-A)
|
|
||||||
if ($node->getRule()->isAssertion()) {
|
if ($node->getRule()->isAssertion()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($this->watches[$node->watch1])) {
|
foreach (array($node->watch1, $node->watch2) as $literal) {
|
||||||
$this->watches[$node->watch1] = null;
|
if (!isset($this->watches[$literal])) {
|
||||||
|
$this->watches[$literal] = new RuleWatchChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->watches[$literal]->unshift($node);
|
||||||
}
|
}
|
||||||
|
|
||||||
$node->next1 = $this->watches[$node->watch1];
|
|
||||||
$this->watches[$node->watch1] = $node;
|
|
||||||
|
|
||||||
if (!isset($this->watches[$node->watch2])) {
|
|
||||||
$this->watches[$node->watch2] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$node->next2 = $this->watches[$node->watch2];
|
|
||||||
$this->watches[$node->watch2] = $node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function contains($literalId)
|
public function contains($literalId)
|
||||||
|
@ -56,79 +46,50 @@ class RuleWatchGraph
|
||||||
public function walkLiteral($literalId, $level, $skipCallback, $conflictCallback, $decideCallback)
|
public function walkLiteral($literalId, $level, $skipCallback, $conflictCallback, $decideCallback)
|
||||||
{
|
{
|
||||||
if (!isset($this->watches[$literalId])) {
|
if (!isset($this->watches[$literalId])) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$prevNode = null;
|
$this->watches[$literalId]->rewind();
|
||||||
for ($node = $this->watches[$literalId]; $node !== null; $prevNode = $node, $node = $nextNode) {
|
while ($this->watches[$literalId]->valid()) {
|
||||||
$nextNode = $node->getNext($literalId);
|
$node = $this->watches[$literalId]->current();
|
||||||
|
|
||||||
if ($node->getRule()->isDisabled()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$otherWatch = $node->getOtherWatch($literalId);
|
$otherWatch = $node->getOtherWatch($literalId);
|
||||||
|
|
||||||
if (call_user_func($skipCallback, $otherWatch)) {
|
if (!$node->getRule()->isDisabled() && !call_user_func($skipCallback, $otherWatch)) {
|
||||||
continue;
|
$ruleLiterals = $node->getRule()->getLiterals();
|
||||||
}
|
|
||||||
|
|
||||||
$ruleLiterals = $node->getRule()->getLiterals();
|
if (sizeof($ruleLiterals) > 2) {
|
||||||
|
foreach ($ruleLiterals as $ruleLiteral) {
|
||||||
|
if ($otherWatch !== $ruleLiteral->getId() &&
|
||||||
|
!call_user_func($conflictCallback, $ruleLiteral->getId())) {
|
||||||
|
|
||||||
if (sizeof($ruleLiterals) > 2) {
|
$this->moveWatch($literalId, $ruleLiteral->getId(), $node);
|
||||||
foreach ($ruleLiterals as $ruleLiteral) {
|
|
||||||
if ($otherWatch !== $ruleLiteral->getId() &&
|
|
||||||
!call_user_func($conflictCallback, $ruleLiteral->getId())) {
|
|
||||||
|
|
||||||
$node = $this->moveWatch($literalId, $ruleLiteral->getId(), $prevNode, $node, $nextNode);
|
continue 2;
|
||||||
|
}
|
||||||
continue 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (call_user_func($conflictCallback, $otherWatch)) {
|
||||||
|
return $node->getRule();
|
||||||
|
}
|
||||||
|
|
||||||
|
call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
|
||||||
}
|
}
|
||||||
|
|
||||||
// yay, we found a unit clause! try setting it to true
|
$this->watches[$literalId]->next();
|
||||||
if (call_user_func($conflictCallback, $otherWatch)) {
|
|
||||||
return $node->getRule();
|
|
||||||
}
|
|
||||||
|
|
||||||
call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function moveWatch($fromLiteral, $toLiteral, $prevNode, $node, $nextNode) {
|
protected function moveWatch($fromLiteral, $toLiteral, $node)
|
||||||
if ($fromLiteral == $node->watch1) {
|
{
|
||||||
$node->watch1 = $toLiteral;
|
if (!isset($this->watches[$toLiteral])) {
|
||||||
$node->next1 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
|
$this->watches[$toLiteral] = new RuleWatchChain;
|
||||||
} else {
|
|
||||||
$node->watch2 = $toLiteral;
|
|
||||||
$node->next2 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($prevNode) {
|
$node->moveWatch($fromLiteral, $toLiteral);
|
||||||
if ($prevNode->next1 === $node) {
|
$this->watches[$fromLiteral]->remove();
|
||||||
$prevNode->next1 = $nextNode;
|
$this->watches[$toLiteral]->unshift($node);
|
||||||
} else {
|
|
||||||
$prevNode->next2 = $nextNode;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->watches[$fromLiteral] = $nextNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->watches[$toLiteral] = $node;
|
|
||||||
|
|
||||||
if ($prevNode) {
|
|
||||||
return $prevNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tmpNode = new RuleWatchNode(new Rule(array(), null, null));
|
|
||||||
$tmpNode->watch1 = $fromLiteral;
|
|
||||||
$tmpNode->next1 = $nextNode;
|
|
||||||
$tmpNode->watch2 = $fromLiteral;
|
|
||||||
$tmpNode->next2 = $nextNode;
|
|
||||||
|
|
||||||
return $tmpNode;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,6 @@ class RuleWatchNode
|
||||||
public $watch1;
|
public $watch1;
|
||||||
public $watch2;
|
public $watch2;
|
||||||
|
|
||||||
public $next1;
|
|
||||||
public $next2;
|
|
||||||
|
|
||||||
public function __construct($rule)
|
public function __construct($rule)
|
||||||
{
|
{
|
||||||
$this->rule = $rule;
|
$this->rule = $rule;
|
||||||
|
@ -64,15 +61,6 @@ class RuleWatchNode
|
||||||
return $this->rule;
|
return $this->rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNext($literalId)
|
|
||||||
{
|
|
||||||
if ($this->watch1 == $literalId) {
|
|
||||||
return $this->next1;
|
|
||||||
} else {
|
|
||||||
return $this->next2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getOtherWatch($literalId)
|
public function getOtherWatch($literalId)
|
||||||
{
|
{
|
||||||
if ($this->watch1 == $literalId) {
|
if ($this->watch1 == $literalId) {
|
||||||
|
@ -81,4 +69,13 @@ class RuleWatchNode
|
||||||
return $this->watch1;
|
return $this->watch1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function moveWatch($from, $to)
|
||||||
|
{
|
||||||
|
if ($this->watch1 == $from) {
|
||||||
|
$this->watch1 = $to;
|
||||||
|
} else {
|
||||||
|
$this->watch2 = $to;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue