/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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, or (at your option) any later version. ### File Specific: main-programmer: Christian Meyer ADDONS/FIXES: Patrick Boenzli : Implemented getSize() function */ /*! \file list.h \brief Contains a template for a doubly linked list */ #ifndef _LIST_TEMPLATE_H #define _LIST_TEMPLATE_H #include "stdincl.h" //! An enum to list all the modes available when adding an object to a List enum ADDMODE {LIST_ADD_NEXT, LIST_ADD_PREV, LIST_ADD_FIRST, LIST_ADD_LAST}; //! An enum to list the two searching directions available when removing an object from a List enum FINDMODE {LIST_FIND_BW, LIST_FIND_FW}; //! A generic doubly linked list template class ListTemplate { T* object; ListTemplate* next; ListTemplate* prev; bool bReference; int size; public: ListTemplate (T* obj, ListTemplate* n, ListTemplate* p, bool bRef); ~ListTemplate (); int add(T* obj, ADDMODE mode, bool bRef); T* getObject(); ListTemplate* getNext(); ListTemplate* getPrevious(); ListTemplate* getLast(); ListTemplate* getFirst(); void setNext(ListTemplate* ptr); void setPrev(ListTemplate* ptr); int remove (T* obj, FINDMODE mode); int getSize(); void destroy(); }; /** \brief Standard constructor Call this without any parameters to generate a new ListTemplate which can be filled with content. DO NOT create a ListTemplate element that contains an object on your own, you'll lose the data contained in that object and will have trouble removing the list from your memory. */ template ListTemplate::ListTemplate (T* obj = NULL, ListTemplate* n = NULL, ListTemplate* p = NULL, bool bRef = false) { object = obj; next = n; prev = p; bReference = bRef; if(obj != NULL) ++size; } /** \brief Standard destructor Call this on the initially generated base ListTemplate element to remove the whole ListTemplate from the memory. You can safely do this to any ListTemplate element you want without messing up the rest of the ListTemplate, but keep in mind that the contained object will be deleted as well when bRef had been set to false. */ template ListTemplate::~ListTemplate () { if (object == NULL) // deleted foot node => disband the list { while( next != NULL) { delete next; } while( prev != NULL) { delete prev; } } else { if (prev != NULL) prev->setNext (next); if (next != NULL) next->setPrev (prev); if (!bReference) delete object; } } /** \brief Add an object to the ListTemplate \param obj: A pointer to an allocated object \param mode: A Value of ADDMODE (default: LIST_ADD_NEXT) \param bRef: Sets whether the element is serving as a storage point or a simple listing (default: false) \return 0 if the operation succeded, -1 if the element could not be added This adds a new ListTemplate element to the chain. The mode parameter can be used to specify the location where the element should be added. LIST_ADD_NEXT will add the new element directly after the base element. LIST_ADD_PREV will add the new element directly before the base element. LIST_ADD_FIRST will add the element at the beginning of the ListTemplate whereas LIST_ADD_LAST will add it to the end of the chain. If the bRef parameter is set to true, the object pointer will not be deleted when the element containing that object is deleted, thus the ListTemplate can be used for temporary listings as well as permanent data storage. */ template int ListTemplate::add (T* obj, ADDMODE mode = LIST_ADD_NEXT, bool bRef = false) { ListTemplate* p; if( obj == NULL) return -1; switch (mode) { case LIST_ADD_NEXT: p = new ListTemplate( obj, next, this, bRef); if( next != NULL) next->setPrev (p); next = p; break; case LIST_ADD_PREV: p = new ListTemplate( obj, this, prev, bRef); if( prev != NULL) prev->setNext (p); prev = p; break; case LIST_ADD_FIRST: if (prev == NULL) prev = new ListTemplate (obj, this, NULL, bRef); else return prev->add (obj, mode, bRef); break; case LIST_ADD_LAST: if (next == NULL) next = new ListTemplate (obj, NULL, this, bRef); else return next->add (obj, mode, bRef); break; default: return -1; break; } ++size; return 0; } /** \brief Get the next element of the ListTemplate \return The ListTemplate element after the current ListTemplate element */ template ListTemplate* ListTemplate::getNext () { return next; } /** \brief Get the previous element of the ListTemplate \return The ListTemplate element before the current ListTemplate element */ template ListTemplate* ListTemplate::getPrevious () { return prev; } /** \brief Get the last element of the ListTemplate \return The last ListTemplate element */ template ListTemplate* ListTemplate::getLast () { if (next == NULL) return this; else return next->getLast(); } /** \brief Get the first element of the ListTemplate \return The first ListTemplate element */ template ListTemplate* ListTemplate::getFirst () { if (prev == NULL) return this; else return prev->getFirst(); } /** \brief Removes a certain element from the ListTemplate \param obj: A pointer to the object that should be removed \param mode: A value of FINDMODE \return 0 if the element was found and removed, -1 if the element was not found This searches the part of the ListTemplate specified with mode for the object in question. When the object is found it is deleted and the ListTemplate element is removed from the chain. If mode is LIST_FIND_FW all elements AFTER the base element are searched, if mode is LIST_FIND_BW all elements BEFORE the base element are searched. Note that the object contained within the ListTemplate element is NOT deleted when bRef was set to true. */ template int ListTemplate::remove (T* obj, FINDMODE mode = LIST_FIND_FW) { if (obj == NULL) return -1; else { switch (mode) { case LIST_FIND_BW: if (prev == NULL) return -1; else { if( prev->getObject() == obj) { delete prev; } else { return prev->remove( obj, mode); } } break; case LIST_FIND_FW: if (next == NULL) return -1; else { if( next->getObject() == obj) { delete next; } else { return next->remove( obj, mode); } } break; default: return -1; } } --size; return 0; } /** \brief Set the next element of a ListTemplate element \param ptr: A pointer to the new next element Sets the next element of a ListTemplate element... Better not touch this, it can really mess up a ListTemplate. */ template void ListTemplate::setNext (ListTemplate* ptr) { next = ptr; } /** \brief Set the prev element of a ListTemplate element \param ptr: A pointer to the new previous element Sets the previous element of a ListTemplate element... Better not touch this, it can really mess up a ListTemplate. */ template void ListTemplate::setPrev (ListTemplate* ptr) { prev = ptr; } /** \brief Get the pointer to the object the element is containing \return The contained object (will be NULL if called on the base element). */ template T* ListTemplate::getObject() { return object; } /** \brief Returns the current size of the ListTemplate \return Size of ListTemplate */ template int ListTemplate::getSize() { return this->size; } template void ListTemplate::destroy() { /* \todo at the moment - doing nothing. should delete everything */ } #endif /* _LIST_TENMPLATE_H */