|
|
80bc9b |
/*
|
|
|
80bc9b |
......... 2015 Ivan Mahonin
|
|
|
80bc9b |
|
|
|
80bc9b |
This program is free software: you can redistribute it and/or modify
|
|
|
80bc9b |
it under the terms of the GNU General Public License as published by
|
|
|
80bc9b |
the Free Software Foundation, either version 3 of the License, or
|
|
|
80bc9b |
(at your option) any later version.
|
|
|
80bc9b |
|
|
|
80bc9b |
This program is distributed in the hope that it will be useful,
|
|
|
80bc9b |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
80bc9b |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
80bc9b |
GNU General Public License for more details.
|
|
|
80bc9b |
|
|
|
80bc9b |
You should have received a copy of the GNU General Public License
|
|
|
80bc9b |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
80bc9b |
*/
|
|
|
80bc9b |
|
|
|
f6cc12 |
using System;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
namespace Contours {
|
|
|
f6cc12 |
public class Circuit<parent, child=""> where Parent: class where Child: class {</parent,>
|
|
|
f6cc12 |
public class Entry {
|
|
|
f6cc12 |
readonly Child owner;
|
|
|
f6cc12 |
Circuit<parent, child=""> circuit;</parent,>
|
|
|
f6cc12 |
Entry previous;
|
|
|
f6cc12 |
Entry next;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Entry(Child owner) { this.owner = owner; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Child getOwner() { return owner; }
|
|
|
f6cc12 |
public Circuit<parent, child=""> getCircuit() { return circuit; }</parent,>
|
|
|
f6cc12 |
public Parent getParent() {
|
|
|
f6cc12 |
Circuit<parent, child=""> circuit = getCircuit();</parent,>
|
|
|
f6cc12 |
return circuit == null ? null : circuit.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Entry getPreviousEntry() { return previous; }
|
|
|
f6cc12 |
public Entry getNextEntry() { return next; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Entry getPreviousEntryLinear() {
|
|
|
f6cc12 |
Entry e = getPreviousEntry();
|
|
|
f6cc12 |
return e == null || e == circuit.last ? null : e;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
public Entry getNextEntryLinear() {
|
|
|
f6cc12 |
Entry e = getNextEntry();
|
|
|
f6cc12 |
return e == null || e == circuit.first ? null : e;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Child getPrevious() {
|
|
|
f6cc12 |
Entry e = getPreviousEntry();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
public Child getNext() {
|
|
|
f6cc12 |
Entry e = getNextEntry();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Child getPreviousLinear() {
|
|
|
f6cc12 |
Entry e = getPreviousEntryLinear();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
public Child getNextLinear() {
|
|
|
f6cc12 |
Entry e = getNextEntryLinear();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void unlink() {
|
|
|
f6cc12 |
if (previous != null) previous.next = next;
|
|
|
f6cc12 |
if (next != null) next.previous = previous;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
if (circuit != null) {
|
|
|
f6cc12 |
if (circuit.first == this) {
|
|
|
f6cc12 |
circuit.first = next != this ? next : null;
|
|
|
f6cc12 |
circuit.last = previous != this ? previous : null;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
--circuit.count;
|
|
|
f6cc12 |
circuit = null;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
previous = null;
|
|
|
f6cc12 |
next = null;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void insertBack(Circuit<parent, child=""> circuit) {</parent,>
|
|
|
f6cc12 |
unlink();
|
|
|
f6cc12 |
if (circuit != null) {
|
|
|
f6cc12 |
if (circuit.empty()) {
|
|
|
f6cc12 |
this.circuit = circuit;
|
|
|
f6cc12 |
previous = next = this;
|
|
|
f6cc12 |
circuit.first = circuit.last = this;
|
|
|
f6cc12 |
++circuit.count;
|
|
|
f6cc12 |
} else {
|
|
|
f6cc12 |
insertAfterOf(circuit.getLastEntry());
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void insertFront(Circuit<parent, child=""> circuit) {</parent,>
|
|
|
f6cc12 |
unlink();
|
|
|
f6cc12 |
if (circuit != null) {
|
|
|
f6cc12 |
if (circuit.empty()) {
|
|
|
f6cc12 |
this.circuit = circuit;
|
|
|
f6cc12 |
previous = next = this;
|
|
|
f6cc12 |
circuit.first = circuit.last = this;
|
|
|
f6cc12 |
++circuit.count;
|
|
|
f6cc12 |
} else {
|
|
|
f6cc12 |
insertBeforeOf(circuit.getFirstEntry());
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void insertAfterOf(Entry entry) {
|
|
|
f6cc12 |
if (entry == this) return;
|
|
|
f6cc12 |
unlink();
|
|
|
f6cc12 |
if (entry == null || entry.getCircuit() == null) return;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
previous = entry;
|
|
|
f6cc12 |
next = entry.next;
|
|
|
f6cc12 |
previous.next = this;
|
|
|
f6cc12 |
if (next != null) next.previous = this;
|
|
|
f6cc12 |
circuit = entry.getCircuit();
|
|
|
f6cc12 |
|
|
|
f6cc12 |
if (circuit != null) {
|
|
|
f6cc12 |
if (circuit.getLastEntry() == entry)
|
|
|
f6cc12 |
circuit.last = this;
|
|
|
f6cc12 |
++circuit.count;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void insertBeforeOf(Entry entry) {
|
|
|
f6cc12 |
if (entry == this) return;
|
|
|
f6cc12 |
unlink();
|
|
|
f6cc12 |
if (entry == null || entry.getCircuit() == null) return;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
previous = entry.previous;
|
|
|
f6cc12 |
next = entry;
|
|
|
f6cc12 |
if (previous != null) previous.next = this;
|
|
|
f6cc12 |
next.previous = this;
|
|
|
f6cc12 |
circuit = entry.getCircuit();
|
|
|
f6cc12 |
|
|
|
f6cc12 |
if (circuit != null) {
|
|
|
f6cc12 |
if (circuit.getFirstEntry() == entry)
|
|
|
f6cc12 |
circuit.first = this;
|
|
|
f6cc12 |
++circuit.count;
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void swapWith(Entry other) {
|
|
|
f6cc12 |
if (other == this || other == null) return;
|
|
|
04c11c |
|
|
|
04c11c |
if (this.next == other || other.previous == this) {
|
|
|
04c11c |
this.next = other.next;
|
|
|
04c11c |
other.next.previous = this;
|
|
|
04c11c |
other.previous = this.previous;
|
|
|
04c11c |
this.previous.next = other;
|
|
|
04c11c |
this.previous = other;
|
|
|
04c11c |
other.next = this;
|
|
|
04c11c |
return;
|
|
|
04c11c |
}
|
|
|
04c11c |
|
|
|
04c11c |
if (other.next == this || this.previous == other) {
|
|
|
04c11c |
other.next = this.next;
|
|
|
04c11c |
this.next.previous = other;
|
|
|
04c11c |
this.previous = other.previous;
|
|
|
04c11c |
other.previous.next = this;
|
|
|
04c11c |
other.previous = this;
|
|
|
04c11c |
this.next = other;
|
|
|
04c11c |
return;
|
|
|
04c11c |
}
|
|
|
04c11c |
|
|
|
04c11c |
if (other.circuit != null) {
|
|
|
04c11c |
if (other.circuit.first == other)
|
|
|
04c11c |
other.circuit.first = this;
|
|
|
04c11c |
if (other.circuit.last == other)
|
|
|
04c11c |
other.circuit.last = this;
|
|
|
04c11c |
}
|
|
|
04c11c |
|
|
|
04c11c |
if (this.circuit != null) {
|
|
|
04c11c |
if (this.circuit.first == this)
|
|
|
04c11c |
this.circuit.first = other;
|
|
|
04c11c |
if (this.circuit.last == this)
|
|
|
04c11c |
this.circuit.last = other;
|
|
|
04c11c |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
Circuit<parent, child=""> otherCircuit = other.circuit;</parent,>
|
|
|
f6cc12 |
Entry otherPrevious = other.previous;
|
|
|
f6cc12 |
Entry otherNext = other.next;
|
|
|
f6cc12 |
|
|
|
04c11c |
other.circuit = this.circuit;
|
|
|
04c11c |
other.previous = this.previous;
|
|
|
04c11c |
other.next = this.next;
|
|
|
f6cc12 |
|
|
|
04c11c |
this.circuit = otherCircuit;
|
|
|
04c11c |
this.previous = otherPrevious;
|
|
|
04c11c |
this.next = otherNext;
|
|
|
f6cc12 |
|
|
|
04c11c |
if (other.previous != null) other.previous.next = other;
|
|
|
04c11c |
if (other.next != null) other.next.previous = other;
|
|
|
04c11c |
if (this.previous != null) this.previous.next = this;
|
|
|
04c11c |
if (this.next != null) this.next.previous = this;
|
|
|
f6cc12 |
}
|
|
|
eb0c54 |
|
|
|
eb0c54 |
public static void swapChains(Circuit<parent, child=""> a, Circuit<parent, child=""> b) {</parent,></parent,>
|
|
|
eb0c54 |
for(Entry e = a.getFirstEntry(); e != null; e = e.getNextEntryLinear())
|
|
|
eb0c54 |
e.circuit = b;
|
|
|
eb0c54 |
for(Entry e = b.getFirstEntry(); e != null; e = e.getNextEntryLinear())
|
|
|
eb0c54 |
e.circuit = a;
|
|
|
eb0c54 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
readonly Parent owner;
|
|
|
f6cc12 |
Entry first;
|
|
|
f6cc12 |
Entry last;
|
|
|
f6cc12 |
int count = 0;
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Circuit(Parent owner) { this.owner = owner; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Parent getOwner() { return owner; }
|
|
|
f6cc12 |
public int getCount() { return count; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Entry getFirstEntry() { return first; }
|
|
|
f6cc12 |
public Entry getLastEntry() { return last; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public Child getFirst() {
|
|
|
f6cc12 |
Entry e = getFirstEntry();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
public Child getLast() {
|
|
|
f6cc12 |
Entry e = getLastEntry();
|
|
|
f6cc12 |
return e == null ? null : e.getOwner();
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public bool empty() { return getFirstEntry() == null; }
|
|
|
f6cc12 |
|
|
|
f6cc12 |
public void clear() {
|
|
|
f6cc12 |
while(!empty()) getFirstEntry().unlink();
|
|
|
f6cc12 |
}
|
|
|
eb0c54 |
|
|
|
eb0c54 |
public void swapWith(Circuit<parent, child=""> other) {</parent,>
|
|
|
eb0c54 |
Entry.swapChains(this, other);
|
|
|
eb0c54 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
}
|
|
|
f6cc12 |
|