Use SplDoublyLinkedList instead of custom linked list

main
Nils Adermann 12 years ago
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;
} }
$node->next1 = $this->watches[$node->watch1]; $this->watches[$literal]->unshift($node);
$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,23 +46,15 @@ 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;
for ($node = $this->watches[$literalId]; $node !== null; $prevNode = $node, $node = $nextNode) {
$nextNode = $node->getNext($literalId);
if ($node->getRule()->isDisabled()) {
continue;
} }
$this->watches[$literalId]->rewind();
while ($this->watches[$literalId]->valid()) {
$node = $this->watches[$literalId]->current();
$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) { if (sizeof($ruleLiterals) > 2) {
@ -80,14 +62,13 @@ class RuleWatchGraph
if ($otherWatch !== $ruleLiteral->getId() && if ($otherWatch !== $ruleLiteral->getId() &&
!call_user_func($conflictCallback, $ruleLiteral->getId())) { !call_user_func($conflictCallback, $ruleLiteral->getId())) {
$node = $this->moveWatch($literalId, $ruleLiteral->getId(), $prevNode, $node, $nextNode); $this->moveWatch($literalId, $ruleLiteral->getId(), $node);
continue 2; continue 2;
} }
} }
} }
// yay, we found a unit clause! try setting it to true
if (call_user_func($conflictCallback, $otherWatch)) { if (call_user_func($conflictCallback, $otherWatch)) {
return $node->getRule(); return $node->getRule();
} }
@ -95,40 +76,20 @@ class RuleWatchGraph
call_user_func($decideCallback, $otherWatch, $level, $node->getRule()); call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
} }
return null; $this->watches[$literalId]->next();
} }
public function moveWatch($fromLiteral, $toLiteral, $prevNode, $node, $nextNode) { return null;
if ($fromLiteral == $node->watch1) {
$node->watch1 = $toLiteral;
$node->next1 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
} else {
$node->watch2 = $toLiteral;
$node->next2 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
}
if ($prevNode) {
if ($prevNode->next1 === $node) {
$prevNode->next1 = $nextNode;
} else {
$prevNode->next2 = $nextNode;
}
} else {
$this->watches[$fromLiteral] = $nextNode;
} }
$this->watches[$toLiteral] = $node; protected function moveWatch($fromLiteral, $toLiteral, $node)
{
if ($prevNode) { if (!isset($this->watches[$toLiteral])) {
return $prevNode; $this->watches[$toLiteral] = new RuleWatchChain;
} }
$tmpNode = new RuleWatchNode(new Rule(array(), null, null)); $node->moveWatch($fromLiteral, $toLiteral);
$tmpNode->watch1 = $fromLiteral; $this->watches[$fromLiteral]->remove();
$tmpNode->next1 = $nextNode; $this->watches[$toLiteral]->unshift($node);
$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,21 +61,21 @@ class RuleWatchNode
return $this->rule; return $this->rule;
} }
public function getNext($literalId) public function getOtherWatch($literalId)
{ {
if ($this->watch1 == $literalId) { if ($this->watch1 == $literalId) {
return $this->next1; return $this->watch2;
} else { } else {
return $this->next2; return $this->watch1;
} }
} }
public function getOtherWatch($literalId) public function moveWatch($from, $to)
{ {
if ($this->watch1 == $literalId) { if ($this->watch1 == $from) {
return $this->watch2; $this->watch1 = $to;
} else { } else {
return $this->watch1; $this->watch2 = $to;
} }
} }
} }

Loading…
Cancel
Save