Blame mono/Contours/Circuit.cs

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