pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_ObjectArrayInternal.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_OBJECTARRAYINTERNAL_H
00040 #define PLONK_OBJECTARRAYINTERNAL_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 //#include "../core/plonk_Sender.h"
00048 #include "../maths/plonk_InlineCommonOps.h"
00049 //#include "plonk_DynamicContainer.h"
00050 
00051 
00052 template<class ObjectType, class BaseType>
00053 class ObjectArrayInternalBase :  public BaseType
00054 {
00055 public: 
00056     typedef ObjectArray<ObjectType> Container;
00057     
00058         ObjectArrayInternalBase (const int size, const bool isNullTerminated) throw();
00059         ObjectArrayInternalBase (const int size, ObjectType *dataToUse, const bool isNullTerminated, const bool shouldTakeOwnership) throw();
00060         ~ObjectArrayInternalBase();
00061         
00062         inline int size() const throw() { return sizeUsed; }
00063     inline int sizeAllocated() const throw() { return allocatedSize; }
00064         inline int length() const throw() 
00065         { 
00066                 if (sizeUsed == 0) 
00067                         return 0;
00068                 else
00069                         return arrayIsNullTerminated ? sizeUsed - 1 : sizeUsed; 
00070         }
00071         
00072         inline ObjectType* getArray() throw() { return array; }
00073         inline const ObjectType* getArray() const throw() { return array; }
00074         inline bool isNullTerminated() const throw() { return arrayIsNullTerminated; }
00075         inline void setNullTerminated (const bool state) throw() { arrayIsNullTerminated = state; } 
00076         
00077     bool setSize (const int newSize, const bool keepContents) throw();
00078     void add (ObjectType const& item) throw();
00079     void add (const int numItems, const ObjectType* items) throw();
00080     void remove (const int index) throw();
00081     int indexOf (ObjectType const& itemToSearchFor, const int startIndex = 0) const throw();
00082         void referTo (const int size, ObjectType *dataToUse, const bool needsNullTermination = false) throw();
00083     void clear() throw();
00084         
00085 private:
00086         int allocatedSize, sizeUsed;
00087         ObjectType *array;
00088         bool arrayIsNullTerminated : 1;
00089         bool ownsTheData : 1;
00090     
00091     void setSizeInternal (const int newSize, const bool keepContents) throw();    
00092     bool setSizeIfNeeded (const int newSize, const bool keepContents) throw();
00093     
00094         ObjectArrayInternalBase();
00095         ObjectArrayInternalBase (const ObjectArrayInternalBase&);
00096         const ObjectArrayInternalBase& operator= (const ObjectArrayInternalBase&);
00097 };
00098 
00099 
00100 //------------------------------------------------------------------------------
00101 
00102 
00103 
00104 template<class ObjectType, class BaseType>
00105 ObjectArrayInternalBase<ObjectType,BaseType>
00106 ::ObjectArrayInternalBase (const int initSize, 
00107                            const bool isNullTerminated) throw()
00108 :       allocatedSize (initSize <= 0 ? 0 : initSize), 
00109     sizeUsed (allocatedSize),
00110     array (allocatedSize == 0 ? 0 : ArrayAllocator<ObjectType>::allocate (allocatedSize)),
00111     arrayIsNullTerminated (isNullTerminated),
00112     ownsTheData (true)
00113 {
00114 }
00115 
00116 template<class ObjectType, class BaseType>
00117 ObjectArrayInternalBase<ObjectType,BaseType>
00118 ::ObjectArrayInternalBase (const int initSize, 
00119                            ObjectType *dataToUse, 
00120                            const bool isNullTerminated,
00121                            const bool shouldTakeOwnership) throw()
00122 :       allocatedSize (shouldTakeOwnership ? initSize : 0),
00123     sizeUsed (initSize),
00124     array (dataToUse),
00125     arrayIsNullTerminated (isNullTerminated),
00126     ownsTheData (shouldTakeOwnership)
00127 {
00128 }
00129 
00130 
00131 template<class ObjectType, class BaseType>
00132 ObjectArrayInternalBase<ObjectType,BaseType>
00133 ::~ObjectArrayInternalBase()
00134 {
00135     if (ownsTheData) 
00136         ArrayAllocator<ObjectType>::free (array);
00137 }
00138 
00139 
00140 template<class ObjectType, class BaseType>
00141 bool ObjectArrayInternalBase<ObjectType,BaseType>
00142 ::setSize (const int newSize, const bool keepContents) throw()
00143 {
00144     const bool didResize = setSizeIfNeeded (newSize, keepContents);
00145     return didResize;
00146 }
00147 
00148 template<class ObjectType, class BaseType>
00149 bool ObjectArrayInternalBase<ObjectType,BaseType>
00150 ::setSizeIfNeeded (const int newSize, const bool keepContents) throw()
00151 {
00152     if (newSize != sizeUsed)
00153     {
00154         sizeUsed = newSize;
00155         
00156         if (newSize > allocatedSize)
00157             setSizeInternal (newSize, keepContents);
00158         
00159         const int newLength = this->length();
00160         
00161         if (allocatedSize > newLength)
00162         {   
00163             // null items beyond the used size and add null termination if needed..
00164             // could avoid this for simple numerical types 
00165             ObjectType null = TypeUtility<ObjectType>::getNull();// ObjectType();
00166             
00167             for (int i = newLength; i < allocatedSize; ++i)
00168                 array[i] = null;
00169         }
00170         
00171         return true;
00172     }
00173     
00174     return false;
00175 }
00176 
00177 
00178 template<class ObjectType, class BaseType>
00179 void ObjectArrayInternalBase<ObjectType,BaseType>
00180 ::setSizeInternal (const int newSize, const bool keepContents) throw()
00181 {    
00182     plonk_assert (newSize >= 0);
00183     plonk_assert (ownsTheData);
00184     
00185     ObjectType* oldArray = array;
00186     
00187     if (newSize <= 0)
00188     {
00189         allocatedSize = 0;
00190         array = 0;
00191     }
00192     else
00193     {        
00194         //const int newSizeWithMargin = (newSize + 7) & ~7; // round to chunks of 8
00195         //..would do this for simple numerical types only.        
00196         ObjectType *newArray = ArrayAllocator<ObjectType>::allocate (newSize);
00197         
00198         if (keepContents)
00199         {
00200             const int overlapSize = plonk::min (allocatedSize, newSize);
00201             
00202             int i;
00203             
00204             // copy existing contents
00205             for (i = 0; i < overlapSize; ++i)
00206                 newArray[i] = array[i];
00207             
00208             // and clear the rest
00209             if (newSize > overlapSize)
00210             {
00211                 ObjectType null = TypeUtility<ObjectType>::getNull();// ObjectType();
00212             
00213                 for (i = overlapSize; i < newSize; ++i)
00214                     newArray[i] = null;
00215             }
00216         }
00217         
00218         allocatedSize = newSize;
00219         array = newArray;   
00220     }
00221     
00222     ArrayAllocator<ObjectType>::free (oldArray);
00223 }
00224 
00225 
00226 template<class ObjectType, class BaseType>
00227 void ObjectArrayInternalBase<ObjectType,BaseType>
00228 ::add (ObjectType const& item) throw()
00229 {
00230     plonk_assert (ownsTheData);
00231     
00232     setSizeIfNeeded (sizeUsed + 1, true);
00233     array[this->length() - 1] = item;
00234 }
00235 
00236 
00237 template<class ObjectType, class BaseType>
00238 void ObjectArrayInternalBase<ObjectType,BaseType>
00239 ::add (const int numItems, const ObjectType* items) throw()
00240 {
00241     plonk_assert (ownsTheData);
00242     plonk_assert (numItems > 0);
00243     
00244     const int originalLength = this->length();    
00245     const int newSize = sizeUsed + numItems;
00246     
00247     setSizeIfNeeded (newSize, true);
00248     
00249     for (int i = originalLength; i < newSize; ++i)
00250         array[i] = *items++;
00251 }
00252 
00253 template<class ObjectType, class BaseType>
00254 void ObjectArrayInternalBase<ObjectType,BaseType>
00255 ::remove (const int index) throw()
00256 {               
00257     plonk_assert (ownsTheData);
00258     
00259     if (index < 0 || index >= sizeUsed) 
00260         return;
00261     
00262     if (allocatedSize == 1)
00263     {        
00264         sizeUsed = 0;
00265     }
00266     else
00267     {
00268         const int newSize = sizeUsed - 1;
00269         
00270         for (int i = index; i < newSize; ++i)
00271             array[i] = array[i + 1];
00272         
00273         ObjectType null = TypeUtility<ObjectType>::getNull();// ObjectType();
00274         array[newSize] = null;//ObjectType();
00275         
00276         sizeUsed = newSize;
00277     }    
00278 }
00279 
00280 template<class ObjectType, class BaseType>
00281 int ObjectArrayInternalBase<ObjectType,BaseType>
00282 ::indexOf (ObjectType const& itemToSearchFor, 
00283            const int startIndex) const throw()
00284 {
00285     if (array != 0)
00286     {
00287         for (int i = startIndex < 0 ? 0 : startIndex; i < sizeUsed; ++i)
00288             if (array[i] == itemToSearchFor)
00289                 return i;
00290     }           
00291     
00292     return -1;
00293 }
00294 
00295 template<class ObjectType, class BaseType>
00296 void ObjectArrayInternalBase<ObjectType,BaseType>
00297 ::referTo (const int newSize, 
00298            ObjectType *dataToUse, 
00299            const bool needsNullTermination) throw()
00300 {
00301     bool needsUpdate = false;
00302     
00303     if (dataToUse == array)
00304     {
00305         if (newSize != sizeUsed)
00306         {
00307             sizeUsed = newSize;
00308             needsUpdate = true;
00309         }
00310         
00311         if (arrayIsNullTerminated != needsNullTermination)
00312         {
00313             arrayIsNullTerminated = needsNullTermination;
00314             needsUpdate = true;
00315             ObjectType null = TypeUtility<ObjectType>::getNull();// ObjectType();
00316             array[this->length()] = null;//ObjectType();
00317         }
00318     }
00319     else 
00320     {
00321         if (ownsTheData)
00322             ArrayAllocator<ObjectType>::free (array);
00323         
00324         allocatedSize = 0;
00325         sizeUsed = newSize;
00326         array = dataToUse;
00327         
00328         arrayIsNullTerminated = needsNullTermination;
00329         ownsTheData = false;
00330         
00331         needsUpdate = true;
00332         
00333         if (array)
00334         {
00335             ObjectType null = TypeUtility<ObjectType>::getNull();// ObjectType();
00336             array[this->length()] = null;//ObjectType();
00337         }
00338     }
00339 }
00340 
00341 template<class ObjectType, class BaseType>
00342 void ObjectArrayInternalBase<ObjectType,BaseType>
00343 ::clear() throw()
00344 {
00345     if (allocatedSize == 0)
00346         return;
00347         
00348     if (ownsTheData)
00349         ArrayAllocator<ObjectType>::free (array);
00350     
00351     allocatedSize = 0;
00352     sizeUsed = 0;
00353     array = 0;    
00354     ownsTheData = true;
00355 }
00356 
00357 template<class ObjectType, class BaseType>
00358 class ObjectArrayInternal : public ObjectArrayInternalBase<ObjectType,BaseType>
00359 {
00360 public:
00361     typedef ObjectArrayInternalBase<ObjectType,BaseType> ObjectArrayInternalBaseType;
00362     
00363     ObjectArrayInternal (const int size, const bool isNullTerminated) throw()
00364     :   ObjectArrayInternalBaseType (size, isNullTerminated)
00365     {
00366     }
00367     
00368         ObjectArrayInternal (const int size, ObjectType *dataToUse, const bool isNullTerminated, const bool shouldTakeOwnership) throw()
00369     :   ObjectArrayInternalBaseType (size, dataToUse, isNullTerminated, shouldTakeOwnership)
00370     {
00371     }
00372 
00373     SmartPointer* deepCopy() const throw()
00374     {
00375         const int size = this->size();
00376         ObjectArrayInternal *theCopy = new ObjectArrayInternal (size, this->isNullTerminated());
00377         const ObjectType* const src = this->getArray();
00378         ObjectType* const dst = theCopy->getArray();
00379         Memory::copy(dst, src, size * sizeof (ObjectType));
00380         return theCopy;
00381     }
00382     
00383 };
00384 
00385 #endif // PLONK_OBJECTARRAYINTERNAL_H
 All Classes Functions Typedefs Enumerations Enumerator Properties