GAM456-SpaceInvaders / SpaceInvaders / 0_Manager / DLink / DLinkMan.cs
DLinkMan.cs
Raw
using System;
using System.Diagnostics;


namespace SpaceInvaders
{
    public class DLinkMan : List
    {
        //-------------------------------------------------------------------
        //  FIELDS
        //-------------------------------------------------------------------

        public DLinkIterator poIterator;

        public DLink pHead;
        public DLink pTail;


        //-------------------------------------------------------------------
        //   CONSTRUCTION
        //-------------------------------------------------------------------

        public DLinkMan() : base()
        {
            //LTN: owned by dlink manager
            this.poIterator = new DLinkIterator();
            Debug.Assert(this.poIterator != null);

            this.pHead = null;
            this.pTail = null;
        }


        //-------------------------------------------------------------------
        //   PUBLIC METHODS
        //-------------------------------------------------------------------

        public override void AddToFront(Node pNode)
        {
            //check node
            Debug.Assert(pNode != null);
            DLink pLink = (DLink)pNode;

            //if list empty, add as head
            if (pHead == null)
            {
                pHead = pTail = pLink;
                pLink.pNext = null;
                pLink.pPrev = null;
            }
            //else, add to front
            else
            {
                //attach new node to head
                pLink.pNext = pHead;
                pLink.pPrev = null;

                //update head
                pHead.pPrev = pLink;
                pHead = pLink;
            }

            Debug.Assert(pHead != null);
        }

        public override void AddByPriority(Node pNode)
        {
            //check node
            Debug.Assert(pNode != null);
            DLink pLink = (DLink)pNode;

            if (this.pHead == null)
            {
                //empty list, add w/o priority check
                this.pHead = this.pTail = pLink;
                pLink.pNext = null;
                pLink.pPrev = null;
            }
            else
            {
                DLink pCurr = this.pHead;
                DLink pPrev = null;

                //iterate list
                while (pCurr != null)
                {
                    if (pCurr.ComparePriority(pLink))
                    {
                        //curr priority <= InNode priority
                        //exit
                        break;
                    }

                    pPrev = pCurr;          //save ref
                    pCurr = pCurr.pNext;    //get next
                }

                if (pCurr == null)
                {
                    //reached end of list, add at end
                    pPrev.pNext = pLink;
                    pLink.pPrev = pPrev;
                    pLink.pNext = null;

                    //update tail ptr
                    this.pTail = pLink;
                }
                else if (pCurr == this.pHead)
                {
                    //add as head
                    pLink.pNext = this.pHead;
                    this.pHead.pPrev = pLink;

                    //update head
                    this.pHead = pLink;
                }
                else
                {
                    //add before 
                    pPrev.pNext = pLink;
                    pCurr.pPrev = pLink;

                    pLink.pPrev = pPrev;
                    pLink.pNext = pCurr;
                }
            }

            Debug.Assert(pHead != null);
        }

        public override void InsertAfter(Node pNewNode, Node pNodeBefore)
        {
            DLink pNewLink = (DLink)pNewNode;
            DLink pPrevLink = (DLink)pNodeBefore;

            pNewLink.pNext = pPrevLink.pNext;
            pNewLink.pPrev = pPrevLink;

            if(pPrevLink.pNext != null)
            {
                pPrevLink.pNext = pNewLink;
            }

            //set previous
            pPrevLink.pNext = pNewLink;
        }

        public override void InsertBefore(Node pNewNode, Node pNodeAfter)
        {
            DLink pNewLink = (DLink)pNewNode;
            DLink pNextLink = (DLink)pNodeAfter;

            //link new node before "next" link
            pNewLink.pNext = pNextLink;
            pNewLink.pPrev = pNextLink.pPrev;

            //head condition
            if(pNextLink.pPrev != null)
            {
                pNextLink.pPrev.pNext = pNewLink;
            }

            //fix next node pointer
            pNextLink.pPrev = pNewLink;
        }

        //active & reserve: remove front node
        public override Node RemoveFromFront()
        {
            //check list exists
            Debug.Assert(pHead != null);

            DLink pLink = pHead;

            //only node on list
            if (pHead.pNext == null)
            {
                //pHead = null;
                pHead = pTail = null;
            }
            //else remove head
            else
            {
                pHead = pHead.pNext;
                pHead.pPrev = null;
            }

            //clear links
            pLink.Reset();

            return pLink;
        }

        //active: remove specific node
        public override void Remove(Node pNode)
        {
            //check node
            Debug.Assert(pHead != null);
            Debug.Assert(pNode != null);

            DLink pLink = (DLink)pNode;
            if (pLink.pPrev == null && pLink.pNext == null)
            {
                //only node on list
                this.pHead = this.pTail = null;
            }
            else if (pLink.pPrev == null && pLink.pNext != null)
            {
                //first node on list
                this.pHead = pLink.pNext;
                pLink.pNext.pPrev = pLink.pPrev;
            }
            else if (pLink == this.pTail)
            {
                //last node
                this.pTail = pTail.pPrev;
                pLink.pPrev.pNext = null;
            }
            else
            {
                //middle node
                pLink.pNext.pPrev = pLink.pPrev;
                pLink.pPrev.pNext = pLink.pNext;
            }

            //clear links
            pLink.Reset();
        }

        public override Iterator GetIterator()
        {
            poIterator.Reset(this.pHead);
            return poIterator;
        }
    }
}