Commit 4d3d0a8f authored by dickelbeck's avatar dickelbeck
Browse files

doubly linked list base class and template for contained specific instantations

parent 43f75cda
Loading
Loading
Loading
Loading

common/dlist.cpp

0 → 100644
+160 −0
Original line number Original line Diff line number Diff line
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (C) 2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 1992-2008 Kicad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */


#include "fctsys.h"
#include "dlist.h"
#include "base_struct.h"


/* Implement the class DHEAD from dlist.h */


DHEAD::~DHEAD()
{
    if( meOwner )
        DestructAll();
}


void DHEAD::DestructAll()
{
    EDA_BaseStruct* next;
    EDA_BaseStruct* item = first;

    while( item )
    {
        next = item->Next();
        delete item;            // virtual destructor, class specific
        item = next;
    }

    first = 0;
    last  = 0;
    count = 0;
}


void DHEAD::Append( EDA_BaseStruct* aNewElement )
{
    wxASSERT( aNewElement != NULL );

    if( first )        // list is not empty, first is not touched
    {
        wxASSERT( last != NULL );

        aNewElement->SetNext( 0 );
        aNewElement->SetBack( last );

        last->SetNext( aNewElement );
        last = aNewElement;
    }
    else        // list is empty, first and last are changed
    {
        aNewElement->SetNext( 0 );
        aNewElement->SetBack( 0 );

        first = aNewElement;
        last  = aNewElement;
    }

    aNewElement->SetList( this );

    ++count;
}


void DHEAD::Insert( EDA_BaseStruct* aNewElement, EDA_BaseStruct* aAfterMe )
{
    wxASSERT( aNewElement != NULL );

    if( !aAfterMe )
        Append( aNewElement );
    else
    {
        wxASSERT( aAfterMe->GetList() == this );

        // the list cannot be empty if aAfterMe is supposedly on the list
        wxASSERT( first && last );

        if( first == aAfterMe )
        {
            aAfterMe->SetBack( aNewElement );

            aNewElement->SetBack( 0 );  // first in list does not point back
            aNewElement->SetNext( aAfterMe );

            first = aNewElement;
        }
        else
        {
            EDA_BaseStruct* oldBack = aAfterMe->Back();

            aAfterMe->SetBack( aNewElement );

            aNewElement->SetBack( oldBack );
            aNewElement->SetNext( aAfterMe );

            oldBack->SetNext( aNewElement );
        }

        aNewElement->SetList( this );

        ++count;
    }
}


void DHEAD::Remove( EDA_BaseStruct* aElement )
{
    wxASSERT( aElement )
    wxASSERT( aElement->GetList() == this );

    if( aElement->Next() )
    {
        aElement->Next()->SetBack( aElement->Back() );
    }
    else
    {
        wxASSERT( last == aElement );
        last = aElement->Back();
    }

    if( aElement->Back() )
    {
        aElement->Back()->SetNext( aElement->Back() );
    }
    else
    {
        wxASSERT( first == aElement );
        first = aElement->Next();
    }

    aElement->SetBack( 0 );
    aElement->SetNext( 0 );
    aElement->SetList( 0 );

    --count;
}

include/dlist.h

0 → 100644
+141 −0
Original line number Original line Diff line number Diff line
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (C) 2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 1992-2008 Kicad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */


#ifndef DLIST_H_
#define DLIST_H_


class EDA_BaseStruct;


/**
 * Class DHEAD
 * is only for use by template class DLIST, use that instead.
 */
class DHEAD
{
protected:
    EDA_BaseStruct*     first;          ///< first element in list, or NULL if list empty
    EDA_BaseStruct*     last;           ///< last elment in list, or NULL if empty
    unsigned            count;          ///< how many elements are in the list
    bool                meOwner;        ///< I must delete the objects in my destructor

    /**
     * Constructor DHEAD
     * is protected so that a DHEAD can only be instantiated from within a
     * DLIST template.
     */
    DHEAD() :
        first(0),
        last(0),
        count(0),
        meOwner(true)
    {
    }

    ~DHEAD();

public:

    /**
     * Function DestructAll
     * deletes all items on the list and leaves the list empty.
     */
    void DestructAll();

    /**
     * Function SetOwnership
     * controls whether the list owns the objects and is responsible for
     * deleteing their memory at time of this object's destruction.
     */
    void SetOwnership( bool Iown ) { meOwner = Iown; }

    /**
     * Function Append
     * adds \a aNewElement to the end of the list.
     */
    void Append( EDA_BaseStruct* aNewElement );

    /**
     * Function Insert
     * puts aNewElement just in front of aElementAfterMe in the list sequence.
     * If aElementAfterMe is NULL, then simply Append()
     */
    void Insert( EDA_BaseStruct* aNewElement, EDA_BaseStruct* aElementAfterMe );

    /**
     * Function Insert
     * puts aNewElement in front of list sequence.
     */
    void Insert( EDA_BaseStruct* aNewElement )
    {
        Insert( aNewElement, first );
    }

    /**
     * Function Remove
     * removes \a aElement from the list, but does not delete it.
     */
    void Remove( EDA_BaseStruct* aElement );

    /**
     * Function GetCount
     * returns the number of elements in the list.
     */
    unsigned GetCount() { return count; }
};


/**
 * Class DLIST
 * is the head of a doubly linked list.  It contains pointers to the first
 * and last elements in a doubly linked list.  The elements in the list must
 * be of class T or derived from T, and T must be derived from EDA_BaseStruct.
 */
template <class T>
class DLIST : public DHEAD
{
public:

    /**
     * operator T*
     * is a casting operator that returns \a first casted to a T*
     */
    operator T* () const { return GetFirst(); }

    /**
     * Function GetFirst
     * returns the first T* in the list, or NULL if the list is empty.
     */
    T*  GetFirst() const { return (T*) first; }

    /**
     * Function GetLast
     * returns the last T* in the list, or NULL if the list is empty.
     */
    T*  GetLast() const { return (T*) last; }
};

#endif      // DLIST_H_