pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_SimpleLinkedList.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 #ifndef PLONK_SIMPLELINKEDLIST_H
00040 #define PLONK_SIMPLELINKEDLIST_H
00041 
00042 #include "../core/plonk_CoreForwardDeclarations.h"
00043 #include "plonk_ContainerForwardDeclarations.h"
00044 
00045 #include "../core/plonk_SmartPointer.h"
00046 #include "../core/plonk_WeakPointer.h"
00047 
00048 template<class ValueType>                                               
00049 class SimpleLinkedListInternal : public SmartPointer
00050 {
00051 public:
00052     typedef SimpleLinkedList<ValueType>        LinkedListType;
00053 
00054     SimpleLinkedListInternal() throw()
00055     {
00056         pl_SimpleLinkedList_Init (&list);
00057         pl_SimpleLinkedList_SetFreeElementDataFunction (&list, SimpleLinkedListInternal::freeElement);
00058     }
00059     
00060     ~SimpleLinkedListInternal()
00061     {
00062         ResultCode result;
00063         
00064         result = pl_SimpleLinkedList_Clear (&list);
00065         plonk_assert (result == PlankResult_OK);
00066 
00067         result = pl_SimpleLinkedList_DeInit (&list);
00068         plonk_assert (result == PlankResult_OK);
00069         
00070 #ifndef PLONK_DEBUG
00071         (void)result;
00072 #endif
00073     }
00074     
00075     void add (ValueType const& value) throw()
00076     {
00077         ResultCode result = pl_SimpleLinkedList_Add (&list, createElement (value));
00078         plonk_assert (result == PlankResult_OK);
00079 #ifndef PLONK_DEBUG
00080         (void)result;
00081 #endif
00082     }
00083     
00084     void insertAtIndex (const LongLong index, ValueType const& value) throw()
00085     {
00086         ResultCode result = pl_SimpleLinkedList_InsertAtIndex (&list, index, createElement (value));
00087         plonk_assert (result == PlankResult_OK);
00088 #ifndef PLONK_DEBUG
00089         (void)result;
00090 #endif
00091     }
00092     
00093     ValueType atIndex (const LongLong index) throw()
00094     {
00095         PlankSimpleLinkedListElementRef element;
00096         ResultCode result = pl_SimpleLinkedList_AtIndex (&list, index, &element);
00097         plonk_assert (result == PlankResult_OK);
00098 #ifndef PLONK_DEBUG
00099         (void)result;
00100 #endif
00101         return getValueFromElement (element);
00102     }
00103     
00104     ValueType getFirst() throw()
00105     {
00106         PlankSimpleLinkedListElementRef element;
00107         ResultCode result = pl_SimpleLinkedList_GetFirst (&list, &element);
00108         plonk_assert (result == PlankResult_OK);
00109 #ifndef PLONK_DEBUG
00110         (void)result;
00111 #endif
00112         return getValueFromElement (element);
00113     }
00114     
00115     ValueType getLast() throw()
00116     {
00117         PlankSimpleLinkedListElementRef element;
00118         ResultCode result = pl_SimpleLinkedList_GetLast (&list, &element);
00119         plonk_assert (result == PlankResult_OK);
00120 #ifndef PLONK_DEBUG
00121         (void)result;
00122 #endif
00123         return getValueFromElement (element);
00124     }
00125     
00126     ValueType removeAtIndex (const LongLong index) throw()
00127     {
00128         PlankSimpleLinkedListElementRef element;
00129         ResultCode result = pl_SimpleLinkedList_RemoveAtIndex (&list, index, &element);
00130         plonk_assert (result == PlankResult_OK);
00131 #ifndef PLONK_DEBUG
00132         (void)result;
00133 #endif
00134         return removeValueFromElement (element);
00135     }
00136     
00137     ValueType removeFirst() throw()
00138     {
00139         PlankSimpleLinkedListElementRef element;
00140         ResultCode result = pl_SimpleLinkedList_RemoveFirst (&list, &element);
00141         plonk_assert (result == PlankResult_OK);
00142 #ifndef PLONK_DEBUG
00143         (void)result;
00144 #endif
00145         return removeValueFromElement (element);
00146     }
00147 
00148     ValueType removeLast() throw()
00149     {
00150         PlankSimpleLinkedListElementRef element;
00151         ResultCode result = pl_SimpleLinkedList_RemoveLast (&list, &element);
00152         plonk_assert (result == PlankResult_OK);
00153 #ifndef PLONK_DEBUG
00154         (void)result;
00155 #endif
00156         return removeValueFromElement (element);
00157     }
00158     
00159     LongLong indexOf (ValueType const& value) throw()
00160     {
00161         PlankSimpleLinkedListElementRef element;
00162         ResultCode result = pl_SimpleLinkedList_GetFirst (&list, &element);
00163         plonk_assert (result == PlankResult_OK);
00164         
00165         LongLong index = 0;
00166         
00167         while (element != 0)
00168         {
00169             if (value == getValueFromElement (element))
00170                 return index;
00171             
00172             ++index;
00173             element = pl_SimpleLinkedListElement_GetNext (element);
00174         }
00175         
00176 #ifndef PLONK_DEBUG
00177         (void)result;
00178 #endif
00179         return -1;
00180     }
00181     
00182     inline LongLong size() throw()
00183     {
00184         return pl_SimpleLinkedList_GetSize (&list);
00185     }
00186     
00187     friend class SimpleLinkedList<ValueType>;
00188     
00189 private:
00190     PlankSimpleLinkedList list;
00191     
00192     inline PlankSimpleLinkedListElementRef createElement (ValueType const& value) throw()
00193     {
00194         PlankSimpleLinkedListElementRef element = pl_SimpleLinkedListElement_CreateAndInit();
00195         plonk_assert (element != 0);
00196         pl_SimpleLinkedListElement_SetData (element, new ValueType (value));
00197         return element;
00198     }
00199     
00200     inline ValueType getValueFromElement (PlankSimpleLinkedListElementRef element) throw()
00201     {
00202         if (element == 0)
00203             return ValueType();
00204         
00205         ValueType* const value = static_cast<ValueType*> (pl_SimpleLinkedListElement_GetData (element));
00206         
00207         if (value != 0)
00208             return *value;
00209         else
00210             return ValueType();
00211     }
00212     
00213     inline ValueType removeValueFromElement (PlankSimpleLinkedListElementRef element) throw()
00214     {
00215         if (element == 0)
00216             return ValueType();
00217         
00218         ValueType* const value = static_cast<ValueType*> (pl_SimpleLinkedListElement_GetData (element));
00219         
00220         ResultCode result = pl_SimpleLinkedListElement_Destroy (element);
00221         plonk_assert (result == PlankResult_OK);
00222 #ifndef PLONK_DEBUG
00223         (void)result;
00224 #endif
00225         
00226         if (value != 0)
00227         {
00228             ValueType result = *value;
00229             delete value;
00230             return result;
00231         }
00232         else
00233         {
00234             return ValueType();
00235         }
00236     }
00237 
00238     static ResultCode freeElement (Pointer data)
00239     {
00240         delete static_cast<ValueType*> (data);
00241         return PlankResult_OK;
00242     }
00243 };
00244 
00245 
00246 template<class ValueType>                                               
00247 class SimpleLinkedListInternal<ValueType*> : public SmartPointer
00248 {
00249 public:
00250     typedef SimpleLinkedList<ValueType*>        LinkedListType;
00251     
00252     SimpleLinkedListInternal() throw()
00253     {
00254         pl_SimpleLinkedList_Init (&list);
00255     }
00256     
00257     ~SimpleLinkedListInternal()
00258     {
00259         plonk_assert (pl_SimpleLinkedList_GetSize (&list) == 0); // pointers were left in the list
00260         pl_SimpleLinkedList_Clear (&list);
00261         pl_SimpleLinkedList_DeInit (&list);        
00262     }
00263         
00264     void add (ValueType* const& value) throw()
00265     {
00266         ResultCode result = pl_SimpleLinkedList_Add (&list, createElement (value));
00267         plonk_assert (result == PlankResult_OK);
00268 #ifndef PLONK_DEBUG
00269         (void)result;
00270 #endif
00271     }
00272     
00273     void insertAtIndex (const LongLong index, ValueType* const& value) throw()
00274     {
00275         ResultCode result = pl_SimpleLinkedList_InsertAtIndex (&list, index, createElement (value));
00276         plonk_assert (result == PlankResult_OK);
00277 #ifndef PLONK_DEBUG
00278         (void)result;
00279 #endif
00280     }
00281     
00282     ValueType* atIndex (const LongLong index) throw()
00283     {
00284         PlankSimpleLinkedListElementRef element;
00285         ResultCode result = pl_SimpleLinkedList_AtIndex (&list, index, &element);
00286         plonk_assert (result == PlankResult_OK);
00287 #ifndef PLONK_DEBUG
00288         (void)result;
00289 #endif
00290         return getValueFromElement (element);
00291     }
00292     
00293     ValueType* getFirst() throw()
00294     {
00295         PlankSimpleLinkedListElementRef element;
00296         ResultCode result = pl_SimpleLinkedList_GetFirst (&list, &element);
00297         plonk_assert (result == PlankResult_OK);
00298 #ifndef PLONK_DEBUG
00299         (void)result;
00300 #endif
00301         return getValueFromElement (element);
00302     }
00303     
00304     ValueType* getLast() throw()
00305     {
00306         PlankSimpleLinkedListElementRef element;
00307         ResultCode result = pl_SimpleLinkedList_GetLast (&list, &element);
00308         plonk_assert (result == PlankResult_OK);
00309 #ifndef PLONK_DEBUG
00310         (void)result;
00311 #endif
00312         return getValueFromElement (element);
00313     }
00314     
00315     ValueType* removeAtIndex (const LongLong index) throw()
00316     {
00317         PlankSimpleLinkedListElementRef element;
00318         ResultCode result = pl_SimpleLinkedList_RemoveAtIndex (&list, index, &element);
00319         plonk_assert (result == PlankResult_OK);
00320 #ifndef PLONK_DEBUG
00321         (void)result;
00322 #endif
00323         return removeValueFromElement (element);
00324     }
00325     
00326     ValueType* removeFirst() throw()
00327     {
00328         PlankSimpleLinkedListElementRef element;
00329         ResultCode result = pl_SimpleLinkedList_RemoveFirst (&list, &element);
00330         plonk_assert (result == PlankResult_OK);
00331 #ifndef PLONK_DEBUG
00332         (void)result;
00333 #endif
00334         return removeValueFromElement (element);
00335     }
00336     
00337     ValueType* removeLast() throw()
00338     {
00339         PlankSimpleLinkedListElementRef element;
00340         ResultCode result = pl_SimpleLinkedList_RemoveLast (&list, &element);
00341         plonk_assert (result == PlankResult_OK);
00342 #ifndef PLONK_DEBUG
00343         (void)result;
00344 #endif
00345         return removeValueFromElement (element);
00346     }
00347     
00348     LongLong indexOf (ValueType* const& value) throw()
00349     {
00350         PlankSimpleLinkedListElementRef element;
00351         ResultCode result = pl_SimpleLinkedList_GetFirst (&list, &element);
00352         plonk_assert (result == PlankResult_OK);
00353         
00354         LongLong index = 0;
00355         
00356         while (element != 0)
00357         {
00358             if (value == getValueFromElement (element))
00359                 return index;
00360             
00361             ++index;
00362             element = pl_SimpleLinkedListElement_GetNext (element);
00363         }
00364         
00365 #ifndef PLONK_DEBUG
00366         (void)result;
00367 #endif
00368         return -1;
00369     }
00370     
00371     inline LongLong size() throw()
00372     {
00373         return pl_SimpleLinkedList_GetSize (&list);
00374     }
00375         
00376     friend class SimpleLinkedList<ValueType*>;
00377     
00378 private:
00379     PlankSimpleLinkedList list;    
00380     
00381     PlankSimpleLinkedListElementRef createElement (ValueType* const& value) throw()
00382     {
00383         PlankSimpleLinkedListElementRef element = pl_SimpleLinkedListElement_CreateAndInit();
00384         plonk_assert (element != 0);
00385         pl_SimpleLinkedListElement_SetData (element, value);
00386         return element;
00387     }
00388     
00389     inline ValueType* getValueFromElement (PlankSimpleLinkedListElementRef element) throw()
00390     {
00391         if (element == 0)
00392             return 0;
00393         
00394         return static_cast<ValueType*> (pl_SimpleLinkedListElement_GetData (element));        
00395     }
00396     
00397     inline ValueType removeValueFromElement (PlankSimpleLinkedListElementRef element) throw()
00398     {
00399         if (element == 0)
00400             return ValueType();
00401         
00402         ValueType* const value = static_cast<ValueType*> (pl_SimpleLinkedListElement_GetData (element));
00403         
00404         ResultCode result = pl_SimpleLinkedListElement_Destroy (element);
00405         plonk_assert (result == PlankResult_OK);
00406 #ifndef PLONK_DEBUG
00407         (void)result;
00408 #endif
00409         
00410         return value;
00411     }
00412 };
00413 
00414 
00415 
00416 //------------------------------------------------------------------------------
00417 
00419 template<class ValueType>                                               
00420 class SimpleLinkedList : public SmartPointerContainer<SimpleLinkedListInternal<ValueType> >
00421 {
00422 public:
00423     typedef SimpleLinkedListInternal<ValueType>     Internal;
00424     typedef SmartPointerContainer<Internal>         Base;
00425     typedef WeakPointerContainer<SimpleLinkedList>  Weak;    
00426 
00427     SimpleLinkedList()
00428     :   Base (new Internal())
00429     {
00430     }
00431     
00432     explicit SimpleLinkedList (Internal* internalToUse) throw() 
00433         :       Base (internalToUse)
00434         {
00435         } 
00436     
00440     static SimpleLinkedList fromWeak (Weak const& weak) throw()
00441     {
00442         return weak.fromWeak();
00443     }    
00444     
00447     SimpleLinkedList (SimpleLinkedList const& copy) throw()
00448     :   Base (static_cast<Base const&> (copy))
00449     {
00450     }
00451     
00452     SimpleLinkedList (Dynamic const& other) throw()
00453     :   Base (other.as<SimpleLinkedList>().getInternal())
00454     {
00455     }    
00456     
00458     SimpleLinkedList& operator= (SimpleLinkedList const& other) throw()
00459         {
00460                 if (this != &other)
00461             this->setInternal (other.getInternal());
00462         
00463         return *this;
00464         }
00465     
00466     inline void add (ValueType const& value) throw()
00467     {
00468         this->getInternal()->add (value);
00469     }
00470     
00471     inline void insertAtIndex (const LongLong index, ValueType const& value) throw()
00472     {
00473         this->getInternal()->insertAtIndex (index, value);
00474     }
00475 
00476     inline ValueType atIndex (const LongLong index) throw()
00477     {
00478         return this->getInternal()->atIndex (index);
00479     }
00480     
00481     inline ValueType getFirst() throw()
00482     {
00483         return this->getInternal()->getFirst();
00484     }
00485     
00486     inline ValueType getLast() throw()
00487     {
00488         return this->getInternal()->getFirst();
00489     }
00490     
00491     inline ValueType removeAtIndex (const LongLong index) throw()
00492     {
00493         return this->getInternal()->removeAtIndex (index);
00494     }
00495     
00496     inline ValueType removeFirst() throw()
00497     {
00498         return this->getInternal()->removeFirst();
00499     }
00500     
00501     inline ValueType removeLast() throw()
00502     {
00503         return this->getInternal()->removeFirst();
00504     }
00505     
00506     inline LongLong indexOf (ValueType const& value) throw()
00507     {
00508         return this->getInternal()->indexOf (value);
00509     }
00510     
00511     inline bool contains (ValueType const& value) throw()
00512     {
00513         return this->getInternal()->indexOf (value) >= 0;
00514     }
00515     
00516     inline LongLong size() throw()
00517     {
00518         return this->getInternal()->size();
00519     }
00520     
00521     PLONK_OBJECTARROWOPERATOR(SimpleLinkedList);
00522 
00523 };
00524 
00525 
00526 #endif // PLONK_SIMPLELINKEDLIST_H
 All Classes Functions Typedefs Enumerations Enumerator Properties