Blame mono/Contours/Circuit.cs

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