![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
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_OBJECTARRAY_H 00040 #define PLONK_OBJECTARRAY_H 00041 00042 #include "../core/plonk_CoreForwardDeclarations.h" 00043 #include "plonk_ContainerForwardDeclarations.h" 00044 #include "plonk_DynamicContainer.h" 00045 00046 #include "../core/plonk_SmartPointerContainer.h" 00047 #include "../core/plonk_WeakPointerContainer.h" 00048 #include "../core/plonk_SenderContainer.h" 00049 #include "../maths/plonk_InlineCommonOps.h" 00050 #include "../random/plonk_RNG.h" 00051 #include "plonk_ObjectArrayInternal.h" 00052 00053 00054 00055 #define ObjectArrayConcatOperatorsDefine(Base, Type)\ 00056 Base<Type> operator<< (Base<Type> const& other) const throw()\ 00057 {\ 00058 return Base<Type>(*this, other);\ 00059 }\ 00060 \ 00061 Base<Type> operator<< (Type const& other) const throw()\ 00062 {\ 00063 return Base<Type>(*this, other);\ 00064 }\ 00065 \ 00066 Base<Type> operator, (Base<Type> const& other) const throw()\ 00067 {\ 00068 return Base<Type>(*this, other);\ 00069 }\ 00070 \ 00071 Base<Type> operator, (Type const& other) const throw()\ 00072 {\ 00073 return Base<Type>(*this, other);\ 00074 }\ 00075 \ 00076 Base<Type>& operator<<= (Base<Type> const& other) throw()\ 00077 {\ 00078 return operator= (Base<Type>(*this, other));\ 00079 }\ 00080 \ 00081 Base<Type>& operator<<= (Type const& other) throw()\ 00082 {\ 00083 return operator= (Base<Type>(*this, other));\ 00084 } 00085 00086 #define ObjectArrayAssignmentDefinition(DerivedArrayType, ElementType)\ 00087 DerivedArrayType& operator= (ObjectArray<ElementType> const& other) throw()\ 00088 {\ 00089 return operator= (static_cast<DerivedArrayType const&> (other) );\ 00090 } 00091 00092 00102 template<class ObjectType> 00103 //class ObjectArray : public SenderContainer< ObjectArrayInternal<ObjectType> > 00104 class ObjectArray : public SmartPointerContainer< ObjectArrayInternal<ObjectType> > 00105 { 00106 public: 00107 typedef ObjectArrayInternal<ObjectType> Internal; 00108 typedef SmartPointerContainer<Internal> Base; 00109 typedef WeakPointerContainer<ObjectArray> Weak; 00110 00111 typedef ObjectArray<ObjectType> ObjectArrayType; 00112 typedef ObjectArray<ObjectArrayType> ObjectArray2DType; 00113 00114 00115 class InitialObject 00116 { 00117 public: 00118 InitialObject() throw() : valid(false) { } 00119 00120 template<class OtherType> 00121 InitialObject (OtherType const& other) throw() 00122 : object (other), valid (true) 00123 { 00124 } 00125 00126 ObjectType object; 00127 const bool valid; 00128 00129 private: 00130 InitialObject& operator= (InitialObject const&); 00131 }; 00132 00134 ObjectArray() throw() 00135 : Base (new Internal (0, false)) 00136 { 00137 } 00138 00139 explicit ObjectArray (Internal* internalToUse) throw() 00140 : Base (internalToUse) 00141 { 00142 } 00143 00147 static ObjectArray fromWeak (Weak const& weak) throw() 00148 { 00149 return weak.fromWeak(); 00150 } 00151 00152 00157 ObjectArray (const int size, const bool needsNullTermination) throw() 00158 : Base (new Internal (size, needsNullTermination)) 00159 { 00160 } 00161 00164 static ObjectArray<ObjectType> withSize (const int size) throw() 00165 { 00166 return ObjectArray<ObjectType> (size, false); 00167 } 00168 00173 static ObjectArray<ObjectType> emptyWithAllocatedSize (const int size) throw() 00174 { 00175 ObjectArray<ObjectType> result = ObjectArray<ObjectType> (size, false); 00176 result.setSize (0, false); 00177 return result; 00178 } 00179 00183 ObjectArray (const int size, ObjectType *dataToUse, const bool needsNullTermination = false, const bool shouldTakeOwnership = false) throw() 00184 : Base (new Internal (size, dataToUse, needsNullTermination, shouldTakeOwnership)) 00185 { 00186 } 00187 00190 inline ObjectArray (ObjectArray const& copy) throw() 00191 : Base (static_cast<Base const&> (copy)) 00192 { 00193 } 00194 00196 ObjectArray& operator= (ObjectArray const& other) throw() 00197 { 00198 if (this != &other) 00199 this->setInternal (other.getInternal());//this->setInternal (other.containerCopy().getInternal()); 00200 00201 return *this; 00202 } 00203 00206 template<class CopyType> 00207 ObjectArray (ObjectArray<CopyType> const& copy) throw() 00208 : Base (new Internal (copy.size(), copy.isNullTerminated())) 00209 { 00210 const int size = this->size(); 00211 00212 for (int i = 0; i < size; ++i) 00213 this->put (i, ObjectType (copy[i])); 00214 } 00215 00218 template<class CollectionType> 00219 static ObjectArray<ObjectType> collect (ObjectArray<CollectionType> const& collection) throw() 00220 { 00221 const int length = collection.length(); 00222 ObjectArray<ObjectType> result (length, false); 00223 00224 for (int i = 0; i < length; ++i) 00225 result.put (i, ObjectType (collection[i])); 00226 00227 return result; 00228 } 00229 00230 template<class CollectionType1, class CollectionType2> 00231 static ObjectArray<ObjectType> collect (ObjectArray<CollectionType1> const& collection1, 00232 ObjectArray<CollectionType2> const& collection2) throw() 00233 { 00234 const int length = plonk::max (collection1.length(), collection2.length()); 00235 ObjectArray<ObjectType> result (length, false); 00236 00237 for (int i = 0; i < length; ++i) 00238 result.put (i, ObjectType (collection1.wrapAt (i), 00239 collection2.wrapAt (i))); 00240 00241 return result; 00242 } 00243 00244 template<class CollectionType1, 00245 class CollectionType2, 00246 class CollectionType3> 00247 static ObjectArray<ObjectType> collect (ObjectArray<CollectionType1> const& collection1, 00248 ObjectArray<CollectionType2> const& collection2, 00249 ObjectArray<CollectionType3> const& collection3) throw() 00250 { 00251 const int length = plonk::max (collection1.length(), 00252 collection2.length(), 00253 collection3.length()); 00254 00255 ObjectArray<ObjectType> result (length, false); 00256 00257 for (int i = 0; i < length; ++i) 00258 result.put (i, ObjectType (collection1.wrapAt (i), 00259 collection2.wrapAt (i), 00260 collection3.wrapAt (i))); 00261 00262 return result; 00263 } 00264 00265 template<class CollectionType1, 00266 class CollectionType2, 00267 class CollectionType3, 00268 class CollectionType4> 00269 static ObjectArray<ObjectType> collect (ObjectArray<CollectionType1> const& collection1, 00270 ObjectArray<CollectionType2> const& collection2, 00271 ObjectArray<CollectionType3> const& collection3, 00272 ObjectArray<CollectionType4> const& collection4) throw() 00273 { 00274 const int length = plonk::max (collection1.length(), 00275 collection2.length(), 00276 collection3.length(), 00277 collection4.length()); 00278 00279 ObjectArray<ObjectType> result (length, false); 00280 00281 for (int i = 0; i < length; ++i) 00282 result.put (i, ObjectType (collection1.wrapAt (i), 00283 collection2.wrapAt (i), 00284 collection3.wrapAt (i), 00285 collection4.wrapAt (i))); 00286 00287 return result; 00288 } 00289 00293 ObjectArray<ObjectType> copy() const throw() 00294 { 00295 const int size = this->size(); 00296 ObjectArray<ObjectType> newArray = ObjectArray<ObjectType> (size, this->isNullTerminated()); 00297 ObjectType *newArrayPtr = newArray.getArray(); 00298 const ObjectType *thisArrayPtr = this->getArray(); 00299 00300 for (int i = 0; i < size; ++i) 00301 newArrayPtr[i] = thisArrayPtr[i]; 00302 00303 return newArray; 00304 } 00305 00307 ObjectArray (ObjectType const& single) throw() 00308 : Base (new Internal (1, false)) 00309 { 00310 this->put (0, single); 00311 } 00312 00313 protected: 00314 static int countValidInitialisers (InitialObject const& i03) throw() 00315 { 00316 int size = 3; 00317 if (i03.valid) size++; else return size; 00318 return size; 00319 } 00320 00321 public: 00322 ObjectArray (InitialObject const &i00, 00323 InitialObject const &i01, 00324 InitialObject const &i02, 00325 InitialObject const &i03 = InitialObject()) throw() 00326 : Base (new Internal (countValidInitialisers (i03), false)) 00327 { 00328 ObjectType *thisArray = this->getArray(); 00329 00330 if (i00.valid) thisArray[ 0] = i00.object; else return; 00331 if (i01.valid) thisArray[ 1] = i01.object; else return; 00332 if (i02.valid) thisArray[ 2] = i02.object; else return; 00333 if (i03.valid) thisArray[ 3] = i03.object; else return; 00334 } 00335 00336 protected: 00337 static int countValidInitialisers (InitialObject const& i05, 00338 InitialObject const& i06, 00339 InitialObject const& i07) throw() 00340 { 00341 int size = 5; 00342 00343 if (i05.valid) size++; else return size; 00344 if (i06.valid) size++; else return size; 00345 if (i07.valid) size++; else return size; 00346 00347 return size; 00348 } 00349 00350 public: 00351 ObjectArray (InitialObject const &i00, 00352 InitialObject const &i01, 00353 InitialObject const &i02, 00354 InitialObject const &i03, 00355 InitialObject const &i04, 00356 InitialObject const &i05 = InitialObject(), 00357 InitialObject const &i06 = InitialObject(), 00358 InitialObject const &i07 = InitialObject()) throw() 00359 : Base (new Internal (countValidInitialisers (i05, i06, i07), false)) 00360 { 00361 ObjectType *thisArray = this->getArray(); 00362 00363 if (i00.valid) thisArray[ 0] = i00.object; else return; 00364 if (i01.valid) thisArray[ 1] = i01.object; else return; 00365 if (i02.valid) thisArray[ 2] = i02.object; else return; 00366 if (i03.valid) thisArray[ 3] = i03.object; else return; 00367 if (i04.valid) thisArray[ 4] = i04.object; else return; 00368 if (i05.valid) thisArray[ 5] = i05.object; else return; 00369 if (i06.valid) thisArray[ 6] = i06.object; else return; 00370 if (i07.valid) thisArray[ 7] = i07.object; else return; 00371 } 00372 00373 protected: 00374 static int countValidInitialisers (InitialObject const& i09, 00375 InitialObject const& i10, 00376 InitialObject const& i11, 00377 InitialObject const& i12, 00378 InitialObject const& i13, 00379 InitialObject const& i14, 00380 InitialObject const& i15) throw() 00381 { 00382 int size = 9; 00383 00384 if (i09.valid) size++; else return size; 00385 if (i10.valid) size++; else return size; 00386 if (i11.valid) size++; else return size; 00387 if (i12.valid) size++; else return size; 00388 if (i13.valid) size++; else return size; 00389 if (i14.valid) size++; else return size; 00390 if (i15.valid) size++; else return size; 00391 00392 return size; 00393 } 00394 00395 public: 00396 ObjectArray (InitialObject const &i00, 00397 InitialObject const &i01, 00398 InitialObject const &i02, 00399 InitialObject const &i03, 00400 InitialObject const &i04, 00401 InitialObject const &i05, 00402 InitialObject const &i06, 00403 InitialObject const &i07, 00404 InitialObject const &i08, 00405 InitialObject const &i09 = InitialObject(), 00406 InitialObject const &i10 = InitialObject(), 00407 InitialObject const &i11 = InitialObject(), 00408 InitialObject const &i12 = InitialObject(), 00409 InitialObject const &i13 = InitialObject(), 00410 InitialObject const &i14 = InitialObject(), 00411 InitialObject const &i15 = InitialObject()) throw() 00412 : Base (new Internal (countValidInitialisers (i09, i10, i11, i12, i13, i14, i15), false)) 00413 { 00414 ObjectType *thisArray = this->getArray(); 00415 00416 if (i00.valid) thisArray[ 0] = i00.object; else return; 00417 if (i01.valid) thisArray[ 1] = i01.object; else return; 00418 if (i02.valid) thisArray[ 2] = i02.object; else return; 00419 if (i03.valid) thisArray[ 3] = i03.object; else return; 00420 if (i04.valid) thisArray[ 4] = i04.object; else return; 00421 if (i05.valid) thisArray[ 5] = i05.object; else return; 00422 if (i06.valid) thisArray[ 6] = i06.object; else return; 00423 if (i07.valid) thisArray[ 7] = i07.object; else return; 00424 if (i08.valid) thisArray[ 8] = i08.object; else return; 00425 if (i09.valid) thisArray[ 9] = i09.object; else return; 00426 if (i10.valid) thisArray[10] = i10.object; else return; 00427 if (i11.valid) thisArray[11] = i11.object; else return; 00428 if (i12.valid) thisArray[12] = i12.object; else return; 00429 if (i13.valid) thisArray[13] = i13.object; else return; 00430 if (i14.valid) thisArray[14] = i14.object; else return; 00431 if (i15.valid) thisArray[15] = i15.object; else return; 00432 } 00433 00434 protected: 00435 static int countValidInitialisers (InitialObject const& i17, 00436 InitialObject const& i18, 00437 InitialObject const& i19, 00438 InitialObject const& i20, 00439 InitialObject const& i21, 00440 InitialObject const& i22, 00441 InitialObject const& i23, 00442 InitialObject const& i24, 00443 InitialObject const& i25, 00444 InitialObject const& i26, 00445 InitialObject const& i27, 00446 InitialObject const& i28, 00447 InitialObject const& i29, 00448 InitialObject const& i30, 00449 InitialObject const& i31) throw() 00450 { 00451 int size = 17; 00452 00453 if (i17.valid) size++; else return size; 00454 if (i18.valid) size++; else return size; 00455 if (i19.valid) size++; else return size; 00456 if (i20.valid) size++; else return size; 00457 if (i21.valid) size++; else return size; 00458 if (i22.valid) size++; else return size; 00459 if (i23.valid) size++; else return size; 00460 if (i24.valid) size++; else return size; 00461 if (i25.valid) size++; else return size; 00462 if (i26.valid) size++; else return size; 00463 if (i27.valid) size++; else return size; 00464 if (i28.valid) size++; else return size; 00465 if (i29.valid) size++; else return size; 00466 if (i30.valid) size++; else return size; 00467 if (i31.valid) size++; else return size; 00468 00469 return size; 00470 } 00471 00472 public: 00473 ObjectArray (InitialObject const &i00, 00474 InitialObject const &i01, 00475 InitialObject const &i02, 00476 InitialObject const &i03, 00477 InitialObject const &i04, 00478 InitialObject const &i05, 00479 InitialObject const &i06, 00480 InitialObject const &i07, 00481 InitialObject const &i08, 00482 InitialObject const &i09, 00483 InitialObject const &i10, 00484 InitialObject const &i11, 00485 InitialObject const &i12, 00486 InitialObject const &i13, 00487 InitialObject const &i14, 00488 InitialObject const &i15, 00489 InitialObject const &i16, 00490 InitialObject const &i17 = InitialObject(), 00491 InitialObject const &i18 = InitialObject(), 00492 InitialObject const &i19 = InitialObject(), 00493 InitialObject const &i20 = InitialObject(), 00494 InitialObject const &i21 = InitialObject(), 00495 InitialObject const &i22 = InitialObject(), 00496 InitialObject const &i23 = InitialObject(), 00497 InitialObject const &i24 = InitialObject(), 00498 InitialObject const &i25 = InitialObject(), 00499 InitialObject const &i26 = InitialObject(), 00500 InitialObject const &i27 = InitialObject(), 00501 InitialObject const &i28 = InitialObject(), 00502 InitialObject const &i29 = InitialObject(), 00503 InitialObject const &i30 = InitialObject(), 00504 InitialObject const &i31 = InitialObject()) throw() 00505 : Base 00506 (new Internal(countValidInitialisers ( i17, i18, i19, 00507 i20, i21, i22, i23, 00508 i24, i25, i26, i27, 00509 i28, i29, i30, i31), 00510 false)) 00511 { 00512 ObjectType *thisArray = this->getArray(); 00513 00514 if (i00.valid) thisArray[ 0] = i00.object; else return; 00515 if (i01.valid) thisArray[ 1] = i01.object; else return; 00516 if (i02.valid) thisArray[ 2] = i02.object; else return; 00517 if (i03.valid) thisArray[ 3] = i03.object; else return; 00518 if (i04.valid) thisArray[ 4] = i04.object; else return; 00519 if (i05.valid) thisArray[ 5] = i05.object; else return; 00520 if (i06.valid) thisArray[ 6] = i06.object; else return; 00521 if (i07.valid) thisArray[ 7] = i07.object; else return; 00522 if (i08.valid) thisArray[ 8] = i08.object; else return; 00523 if (i09.valid) thisArray[ 9] = i09.object; else return; 00524 if (i10.valid) thisArray[10] = i10.object; else return; 00525 if (i11.valid) thisArray[11] = i11.object; else return; 00526 if (i12.valid) thisArray[12] = i12.object; else return; 00527 if (i13.valid) thisArray[13] = i13.object; else return; 00528 if (i14.valid) thisArray[14] = i14.object; else return; 00529 if (i15.valid) thisArray[15] = i15.object; else return; 00530 if (i16.valid) thisArray[16] = i16.object; else return; 00531 if (i17.valid) thisArray[17] = i17.object; else return; 00532 if (i18.valid) thisArray[18] = i18.object; else return; 00533 if (i19.valid) thisArray[19] = i19.object; else return; 00534 if (i20.valid) thisArray[20] = i20.object; else return; 00535 if (i21.valid) thisArray[21] = i21.object; else return; 00536 if (i22.valid) thisArray[22] = i22.object; else return; 00537 if (i23.valid) thisArray[23] = i23.object; else return; 00538 if (i24.valid) thisArray[24] = i24.object; else return; 00539 if (i25.valid) thisArray[25] = i25.object; else return; 00540 if (i26.valid) thisArray[26] = i26.object; else return; 00541 if (i27.valid) thisArray[27] = i27.object; else return; 00542 if (i28.valid) thisArray[28] = i28.object; else return; 00543 if (i29.valid) thisArray[29] = i29.object; else return; 00544 if (i30.valid) thisArray[30] = i30.object; else return; 00545 if (i31.valid) thisArray[31] = i31.object; else return; 00546 } 00547 00548 00550 ObjectArray (ObjectArray<ObjectType> const& array0, 00551 ObjectArray<ObjectType> const& array1) throw() 00552 : Base (new Internal (0, false)) 00553 { 00554 const bool bothNullTerminated = array0.isNullTerminated() && array1.isNullTerminated(); 00555 const bool eitherNullTerminated = array0.isNullTerminated() || array1.isNullTerminated(); 00556 const int summedSizes = array0.size() + array1.size(); 00557 const int newSize = bothNullTerminated ? summedSizes - 1 : summedSizes; 00558 00559 if (newSize > 0) 00560 { 00561 this->setInternal (new Internal (newSize, eitherNullTerminated)); 00562 00563 int newIndex = 0; 00564 00565 ObjectType *array = this->getArray(); 00566 00567 if (array != 0) 00568 { 00569 const ObjectType *arrayPtr0 = array0.getArray(); 00570 const ObjectType *arrayPtr1 = array1.getArray(); 00571 00572 int i; 00573 for (i = 0; i < array0.length(); ++i) 00574 { 00575 array[newIndex++] = arrayPtr0[i]; 00576 } 00577 00578 for (i = 0; i < array1.length(); ++i) 00579 { 00580 array[newIndex++] = arrayPtr1[i]; 00581 } 00582 00583 if (eitherNullTerminated) 00584 array[newIndex] = getNullObject(); 00585 } 00586 } 00587 } 00588 00594 inline bool setSize (const int newSize, const bool keepContents) throw() 00595 { 00596 return this->getInternal()->setSize (newSize, keepContents); 00597 } 00598 00600 inline void clear() throw() 00601 { 00602 this->getInternal()->setSize (isNullTerminated() ? 1 : 0, false); 00603 } 00604 00607 inline int size() const throw() { return this->getInternal()->size(); } 00608 00611 inline int sizeAllocated() const throw() { return this->getInternal()->sizeAllocated(); } 00612 00616 inline int length() const throw() { return this->getInternal()->length(); } 00617 00620 inline int memorySize() const throw() { return this->getInternal()->size() * sizeof(ObjectType); } 00621 00623 inline ObjectType* getArray() throw() { return this->getInternal()->getArray(); } 00624 00626 inline const ObjectType* getArray() const throw() { return this->getInternal()->getArray(); } 00627 00629 inline operator const ObjectType*() const throw() { return this->getArray(); } 00631 inline operator ObjectType*() throw() { return this->getArray(); } 00632 00634 inline bool isNullTerminated() const throw() { return this->getInternal()->isNullTerminated(); } 00635 00637 inline void setNullTerminated (const bool state) throw() { this->getInternal()->setNullTerminated(state); } 00638 00639 ObjectArrayConcatOperatorsDefine(ObjectArray, ObjectType); 00640 00645 void referTo (const int size, ObjectType *dataToUse, const bool needsNullTermination = false) 00646 { 00647 this->getInternal()->referTo (size, dataToUse, needsNullTermination); 00648 } 00649 00651 ObjectArray<ObjectType>& add (ObjectType const& item) throw() 00652 { 00653 this->getInternal()->add (item); 00654 return *this; 00655 } 00656 00658 ObjectArray<ObjectType>& add (ObjectArray<ObjectType> const& other) throw() // had changed to addAll but caused other errors. add is nice polymorphism! 00659 { 00660 this->getInternal()->add (other.length(), other.getArray()); 00661 return *this; 00662 } 00663 00666 ObjectArray<ObjectType>& remove (const int index) throw() 00667 { 00668 this->getInternal()->remove (index); 00669 return *this; 00670 } 00671 00674 ObjectArray<ObjectType>& put (const int index, ObjectType const& item) throw() 00675 { 00676 if (index < 0 || index >= this->size()) 00677 return *this; 00678 00679 this->getArray()[index] = item; 00680 00681 return *this; 00682 } 00683 00687 ObjectType& operator[] (const int index) throw() 00688 { 00689 if (index < 0 || index >= this->size()) 00690 return getNullObject(); 00691 else 00692 return this->getArray()[index]; 00693 } 00694 00698 const ObjectType& operator[] (const int index) const throw() 00699 { 00700 if (index < 0 || index >= this->size()) 00701 return getNullObject(); 00702 else 00703 return this->getArray()[index]; 00704 } 00705 00709 ObjectType& at (const int index) throw() 00710 { 00711 if (index < 0 || index >= this->size()) 00712 return getNullObject(); 00713 else 00714 return this->getArray()[index]; 00715 } 00716 00720 const ObjectType& at (const int index) const throw() 00721 { 00722 if (index < 0 || index >= this->size()) 00723 return getNullObject(); 00724 else 00725 return this->getArray()[index]; 00726 } 00727 00729 ObjectArray<ObjectType> at (ObjectArray<int> const& indices) const throw() 00730 { 00731 if (this->getInternal()->size() == 0) { return *this; } 00732 00733 const bool needsNull = this->isNullTerminated(); 00734 const int length = indices.length(); 00735 const int size = needsNull ? length + 1 : length; 00736 00737 ObjectArray<ObjectType> result (size, needsNull); 00738 ObjectType* resultArray = result.getArray(); 00739 const ObjectType* thisArray = this->getArray(); 00740 00741 const int thisSize = this->size(); 00742 for (int i = 0; i < length; ++i) 00743 { 00744 const int index = indices[i]; 00745 resultArray[i] = index < 0 || index >= thisSize ? getNullObject() : thisArray[index]; 00746 } 00747 00748 if (needsNull) 00749 resultArray[length] = getNullObject(); 00750 00751 return result; 00752 } 00753 00755 ObjectArray<ObjectType> atUnchecked (ObjectArray<int> const& indices) const throw() 00756 { 00757 const bool needsNull = this->isNullTerminated(); 00758 const int length = indices.length(); 00759 const int size = needsNull ? length + 1 : length; 00760 00761 ObjectArray<ObjectType> result(size, needsNull); 00762 ObjectType* resultArray = result.getArray(); 00763 const ObjectType* thisArray = this->getArray(); 00764 00765 for (int i = 0; i < length; ++i) 00766 { 00767 const int index = indices[i]; 00768 resultArray[i] = thisArray[index]; 00769 } 00770 00771 if (needsNull) 00772 resultArray[length] = getNullObject(); 00773 00774 return result; 00775 } 00776 00777 00780 inline ObjectType& atUnchecked (const int index) throw() 00781 { 00782 plonk_assert ((index >= 0) && (index < this->getInternal()->size())); 00783 return this->getInternal()->getArray()[index]; 00784 } 00785 00788 inline const ObjectType& atUnchecked (const int index) const throw() 00789 { 00790 plonk_assert ((index >= 0) && (index < this->getInternal()->size())); 00791 return this->getInternal()->getArray()[index]; 00792 } 00793 00798 ObjectType& wrapAt (const int index) throw() 00799 { 00800 if (this->getInternal()->size() == 0) { return getNullObject(); } 00801 00802 int indexToUse = index; 00803 while (indexToUse < 0) 00804 indexToUse += this->size(); 00805 00806 return this->getArray()[(unsigned int)indexToUse % (unsigned int)this->size()]; 00807 } 00808 00813 const ObjectType& wrapAt (const int index) const throw() 00814 { 00815 if (this->getInternal()->size() == 0) { return getNullObject(); } 00816 00817 int indexToUse = index; 00818 while (indexToUse < 0) 00819 indexToUse += this->size(); 00820 00821 return this->getArray()[(unsigned int)indexToUse % (unsigned int)this->size()]; 00822 } 00823 00826 ObjectType& first() throw() 00827 { 00828 if (this->getInternal()->size() == 0) 00829 return getNullObject(); 00830 else 00831 return this->getArray()[0]; 00832 } 00833 00836 const ObjectType& first() const throw() 00837 { 00838 if (this->getInternal()->size() == 0) 00839 return getNullObject(); 00840 else 00841 return this->getArray()[0]; 00842 } 00843 00846 ObjectType& last() throw() 00847 { 00848 if (this->getInternal()->size() == 0) 00849 return getNullObject(); 00850 else 00851 return this->getArray()[this->size() - 1]; 00852 } 00853 00856 const ObjectType& last() const throw() 00857 { 00858 if (this->getInternal()->size() == 0) 00859 return getNullObject(); 00860 else 00861 return this->getArray()[this->size() - 1]; 00862 } 00863 00867 ObjectType& choose() throw() 00868 { 00869 if (this->getInternal()->size() == 0) 00870 return getNullObject(); 00871 else 00872 return this->getArray()[plonk::rand (this->length())]; 00873 } 00874 00878 const ObjectType& choose() const throw() 00879 { 00880 if (this->getInternal()->size() == 0) 00881 return getNullObject(); 00882 else 00883 return this->getArray()[plonk::rand (this->length())]; 00884 } 00885 00894 template<class WeightType> 00895 ObjectType& wchoose (ObjectArray<WeightType> const& weights) throw() 00896 { 00897 if (this->getInternal()->size() == 0) 00898 { 00899 return getNullObject(); 00900 } 00901 else 00902 { 00903 const int length = this->length(); 00904 ObjectArray<WeightType> thresholds = ObjectArray<WeightType> (length, false); 00905 00906 WeightType sum = 0; 00907 int i; 00908 for (i = 0; i < length; ++i) 00909 { 00910 sum += weights.wrapAt (i); 00911 thresholds[i] = sum; 00912 } 00913 00914 const WeightType random = plonk::rand (sum); 00915 00916 for (i = 0; i < length; ++i) 00917 { 00918 if (random < thresholds[i]) 00919 return this->getArray()[i]; 00920 } 00921 00922 return this->getArray()[length-1]; 00923 } 00924 } 00925 00934 template<class WeightType> 00935 const ObjectType& wchoose (ObjectArray<WeightType> const& weights) const throw() 00936 { 00937 if (this->getInternal()->size() == 0) 00938 { 00939 return getNullObject(); 00940 } 00941 else 00942 { 00943 const int length = this->length(); 00944 ObjectArray<WeightType> thresholds = ObjectArray<WeightType> (length, false); 00945 00946 WeightType sum = 0; 00947 int i; 00948 for (i = 0; i < length; i++) 00949 { 00950 sum += weights.wrapAt (i); 00951 thresholds[i] = sum; 00952 } 00953 00954 const WeightType random = plonk::rand (sum); 00955 00956 for (i = 0; i < length; i++) 00957 { 00958 if (random < thresholds[i]) 00959 return this->getArray()[i]; 00960 } 00961 00962 return this->getArray()[length-1]; 00963 } 00964 } 00965 00966 ObjectArray<ObjectType> rotate (const int amount) throw() 00967 { 00968 return this->range (amount, this->length()).add (this->range (0, amount)); 00969 } 00970 00973 bool areAllEqual() const throw() 00974 { 00975 if (this->length() > 0) 00976 { 00977 const ObjectType *thisArray = this->getArray(); 00978 const ObjectType first = thisArray[0]; 00979 00980 for (int i = 1; i < this->length(); ++i) 00981 if (thisArray[i] != first) 00982 return false; 00983 } 00984 00985 return true; 00986 } 00987 00988 static const ObjectArray& getNull() throw() 00989 { 00990 static ObjectArray null; 00991 return null; 00992 } 00993 00994 static ObjectType& getNullObject() throw() 00995 { 00996 static ObjectType null; 00997 null = ObjectType(); 00998 return null; 00999 } 01000 01001 // static const ObjectType& getNullObject() throw() 01002 // { 01003 // return TypeUtility<ObjectType>::getNull(); 01004 // } 01005 01007 bool operator== (ObjectArray<ObjectType> const& other) const throw() 01008 { 01009 const ObjectType *thisArray = this->getArray(); 01010 const ObjectType *otherArray = other.getArray(); 01011 01012 if (thisArray == otherArray) 01013 return true; 01014 01015 const int size = this->size(); 01016 01017 if (size != other.size()) 01018 return false; 01019 01020 if (size == 0) 01021 return true; 01022 01023 for (int i = 0; i < size; ++i) 01024 if (thisArray[i] != otherArray[i]) 01025 return false; 01026 01027 return true; 01028 } 01029 01031 bool operator== (const ObjectType* otherArray) const throw() 01032 { 01033 plonk_assert (otherArray != 0); 01034 01035 const ObjectType *thisArray = this->getArray(); 01036 01037 if (thisArray == otherArray) 01038 return true; 01039 01040 const int size = this->size(); 01041 01042 for (int i = 0; i < size; ++i) 01043 if (thisArray[i] != otherArray[i]) 01044 return false; 01045 01046 return true; 01047 } 01048 01050 bool operator!= (ObjectArray<ObjectType> const& other) const throw() 01051 { 01052 return !operator== (other); 01053 } 01054 01056 bool operator!= (const ObjectType* otherArray) const throw() 01057 { 01058 return !operator== (otherArray); 01059 } 01060 01062 bool contains (ObjectType const& itemToSearchFor) const throw() 01063 { 01064 const ObjectType *array = this->getArray(); 01065 01066 if (array != 0) 01067 { 01068 const int size = this->size(); 01069 01070 for (int i = 0; i < size; ++i) 01071 if (array[i] == itemToSearchFor) 01072 return true; 01073 } 01074 01075 return false; 01076 } 01077 01080 bool contains (ObjectArray<ObjectType> const& itemsToSearchFor) const throw() 01081 { 01082 const ObjectType *array = this->getArray(); 01083 const ObjectType *items = itemsToSearchFor.getArray(); 01084 01085 if (array != 0 && items != 0) 01086 { 01087 const int length = this->length(); 01088 int itemsToFind = itemsToSearchFor.length(); 01089 01090 if (length == 0 || itemsToFind == 0) 01091 return false; 01092 01093 int nextIndexToFind = 0; 01094 01095 for (int i = 0; i < length; ++i) 01096 { 01097 if (array[i] == items[nextIndexToFind]) 01098 { 01099 itemsToFind--; 01100 01101 while (itemsToFind > 0) 01102 { 01103 i++; 01104 nextIndexToFind++; 01105 01106 if ((i > length) || (array[i] != items[nextIndexToFind])) 01107 return false; 01108 01109 itemsToFind--; 01110 } 01111 01112 return true; 01113 } 01114 } 01115 } 01116 01117 return false; 01118 } 01119 01124 int indexOf (ObjectType const& itemToSearchFor, const int startIndex = 0) const throw() 01125 { 01126 const ObjectType *array = this->getArray(); 01127 01128 if (array != 0) 01129 { 01130 const int size = this->size(); 01131 for (int i = startIndex < 0 ? 0 : startIndex; i < size; ++i) 01132 if (array[i] == itemToSearchFor) 01133 return i; 01134 } 01135 01136 return -1; 01137 } 01138 01140 int indexOf (ObjectArray<ObjectType> const& itemsToSearchFor, const int startIndex = 0) const throw() 01141 { 01142 const ObjectType *array = this->getArray(); 01143 const ObjectType *items = itemsToSearchFor.getArray(); 01144 01145 if (array != 0 && items != 0) 01146 { 01147 const int length = this->length(); 01148 int itemsToFind = itemsToSearchFor.length(); 01149 01150 if (length == 0 || itemsToFind == 0) 01151 return -1; 01152 01153 int nextIndexToFind = 0; 01154 01155 for (int i = startIndex < 0 ? 0 : startIndex; i < length; ++i) 01156 { 01157 if (array[i] == items[nextIndexToFind]) 01158 { 01159 int foundAtIndex = i; 01160 01161 itemsToFind--; 01162 01163 while (itemsToFind > 0) 01164 { 01165 i++; 01166 nextIndexToFind++; 01167 01168 if ((i > length) || (array[i] != items[nextIndexToFind])) 01169 return -1; 01170 01171 itemsToFind--; 01172 } 01173 01174 return foundAtIndex; 01175 } 01176 } 01177 } 01178 01179 return -1; 01180 } 01181 01183 int indexOfAny (ObjectArray<ObjectType> const& itemsToSearchFor, const int startIndex = 0) const throw() 01184 { 01185 const ObjectType *array = this->getArray(); 01186 01187 if (array != 0) 01188 { 01189 const int length = this->length(); 01190 const int itemsToFind = itemsToSearchFor.length(); 01191 01192 if (length == 0 || itemsToFind == 0) 01193 return -1; 01194 01195 for (int i = startIndex < 0 ? 0 : startIndex; i < length; ++i) 01196 if (itemsToSearchFor.contains (array[i])) 01197 return i; 01198 } 01199 01200 return -1; 01201 } 01202 01205 ObjectArray<ObjectType> from (const int startIndex) const throw() 01206 { 01207 return range (startIndex); 01208 } 01209 01212 ObjectArray<ObjectType> range (const int startIndex) const throw() 01213 { 01214 return this->range (startIndex, 0x7fffffff); 01215 } 01216 01219 ObjectArray<ObjectType> to (const int endIndex) const throw() 01220 { 01221 return range (0, endIndex); 01222 } 01223 01226 ObjectArray<ObjectType> range (const int startIndex, const int endIndex) const throw() 01227 { 01228 const int size = this->size(); 01229 01230 if (size == 0) 01231 return ObjectArray<ObjectType>(); 01232 01233 const int startIndexChecked = startIndex < 0 ? 0 : startIndex; 01234 const int endIndexChecked = endIndex > size ? size : endIndex; 01235 01236 if (startIndexChecked >= endIndexChecked) return ObjectArray<ObjectType>(); 01237 01238 const ObjectType *sourceArray = this->getArray(); 01239 01240 if (sourceArray == 0) 01241 return ObjectArray<ObjectType>(); 01242 01243 const bool needsNull = this->isNullTerminated(); 01244 01245 const int diff = endIndexChecked - startIndexChecked; 01246 const int newSize = needsNull && (endIndexChecked < size) ? diff + 1 : diff; 01247 01248 ObjectArray<ObjectType> result (newSize, needsNull); 01249 ObjectType *resultArray = result.getArray(); 01250 01251 int resultIndex = 0; 01252 for (int sourceIndex = startIndexChecked; sourceIndex < endIndexChecked; ++sourceIndex) 01253 resultArray[resultIndex++] = sourceArray[sourceIndex]; 01254 01255 if (needsNull) 01256 resultArray[resultIndex] = this->getNullObject(); 01257 01258 return result; 01259 } 01260 01263 ObjectArray<ObjectType> replace (ObjectArray<ObjectType> const& find, ObjectArray<ObjectType> const& substitute) const throw() 01264 { 01265 const int size = this->size(); 01266 const int findLength = find.length(); 01267 int startIndex = 0; 01268 int findIndex; 01269 01270 ObjectArray<ObjectType> result; 01271 01272 while ((findIndex = this->indexOf (find, startIndex)) >= 0) 01273 { 01274 result.add (this->range (startIndex, findIndex)); 01275 result.add (substitute); 01276 startIndex = findIndex + findLength; 01277 } 01278 01279 result.add (this->range (startIndex, size)); 01280 01281 return result; 01282 } 01283 01285 ObjectArray<ObjectType>& removeItem (const ObjectType item) throw() 01286 { 01287 const int index = this->indexOf (item); 01288 01289 if (index >= 0) 01290 this->getInternal()->remove (index); 01291 01292 return *this; 01293 } 01294 01296 ObjectArray<ObjectType>& removeItems (ObjectArray<ObjectType> const& items) throw() 01297 { 01298 for (int i = 0; i < items.length(); i++) 01299 this->removeItem (items[i]); 01300 01301 return *this; 01302 } 01303 01305 ObjectArray2DType group (const int groupSize) const throw() 01306 { 01307 const int length = this->length(); 01308 01309 if (length == 0) 01310 return ObjectArray<ObjectType>(); 01311 01312 const int groupSizeChecked = groupSize < 1 ? 1 : groupSize; 01313 const int groupSizeMinus1 = groupSizeChecked - 1; 01314 const bool needsNull = this->isNullTerminated(); 01315 01316 ObjectArray< ObjectArray<ObjectType> > result; 01317 ObjectArray<ObjectType> element; 01318 01319 const ObjectType *thisArray = this->getArray(); 01320 01321 for (int i = 0; i < length; ++i) 01322 { 01323 element.add (thisArray[i]); 01324 01325 if ((i % groupSizeChecked) == groupSizeMinus1) 01326 { 01327 if (needsNull) 01328 { 01329 element.add (this->getNullObject()); 01330 element.setNullTerminated (true); 01331 } 01332 01333 result.add (element); 01334 element = ObjectArray<ObjectType>(); // reset 01335 } 01336 } 01337 01338 if (element.length() != 0) 01339 { 01340 if (needsNull) 01341 { 01342 element.add (this->getNullObject()); 01343 element.setNullTerminated (true); 01344 } 01345 01346 result.add (element); 01347 } 01348 01349 return result; 01350 } 01351 01354 ObjectArray2DType split (ObjectArray<ObjectType> delimiters) const throw() 01355 { 01356 const int length = this->length(); 01357 01358 if (length == 0) 01359 return ObjectArray<ObjectType>(); 01360 01361 const bool needsNull = this->isNullTerminated(); 01362 01363 ObjectArray< ObjectArray<ObjectType> > result; 01364 ObjectArray<ObjectType> element; 01365 01366 const ObjectType *thisArray = this->getArray(); 01367 01368 if (thisArray != 0) 01369 { 01370 for (int i = 0; i < length; ++i) 01371 { 01372 const ObjectType item = thisArray[i]; 01373 01374 if (delimiters.contains(item)) 01375 { 01376 if (element.length() > 0) 01377 { 01378 if (needsNull) 01379 { 01380 element.add (this->getNullObject()); 01381 element.setNullTerminated (true); 01382 } 01383 01384 result.add (element); 01385 element = ObjectArray<ObjectType>(); // reset 01386 } 01387 } 01388 else 01389 { 01390 element.add (item); 01391 } 01392 } 01393 01394 if (element.length() != 0) 01395 { 01396 if (needsNull) 01397 { 01398 element.add (this->getNullObject()); 01399 element.setNullTerminated (true); 01400 } 01401 01402 result.add (element); 01403 } 01404 } 01405 01406 return result; 01407 } 01408 01411 ObjectArray2DType splitSequence (ObjectArray<ObjectType> delimitingSequence) const throw() 01412 { 01413 const int size = this->size(); 01414 ObjectArray< ObjectArray<ObjectType> > result; 01415 01416 if (size != 0) 01417 { 01418 const int findLength = delimitingSequence.length(); 01419 int startIndex = 0; 01420 int findIndex; 01421 01422 while ((findIndex = this->indexOf (delimitingSequence, startIndex)) >= 0) 01423 { 01424 result.add (this->range (startIndex, findIndex)); 01425 startIndex = findIndex + findLength; 01426 } 01427 01428 result.add (this->range (startIndex, size)); 01429 } 01430 01431 return result; 01432 } 01433 01444 ObjectArray2DType deinterleave (const int numGroups) const throw() 01445 { 01446 int i, j; 01447 01448 plonk_assert (!this->isNullTerminated()); // could be done but need this for audio de-interleaving for now.. 01449 01450 const int length = this->length(); 01451 01452 if (length == 0) 01453 return ObjectArray<ObjectType>(); 01454 01455 plonk_assert (numGroups > 0); 01456 01457 const int subLength = ((unsigned int)length % (unsigned int)numGroups) == 0 01458 ? (unsigned int)length / (unsigned int)numGroups 01459 : (unsigned int)length / (unsigned int)numGroups + 1; 01460 01461 ObjectArray2DType result = ObjectArray2DType::withSize (numGroups); 01462 ObjectArray* const resultArray = result.getArray(); 01463 01464 int lengthRemaining = length; 01465 01466 for (i = 0; i < numGroups; ++i) 01467 { 01468 const int subLengthUsed = plonk::min (subLength, lengthRemaining); 01469 ObjectArray sub = ObjectArray::withSize (subLengthUsed); 01470 ObjectType* const subArray = sub.getArray(); 01471 01472 const ObjectType *thisArray = this->getArray() + i; 01473 01474 for (j = 0; j < subLengthUsed; ++j, thisArray += numGroups) 01475 subArray[j] = *thisArray; 01476 01477 resultArray[i] = sub; 01478 lengthRemaining -= subLengthUsed; 01479 } 01480 01481 return result; 01482 } 01483 01484 PLONK_OBJECTARROWOPERATOR(ObjectArray); 01485 01486 // static void deinterleave (ObjectType* dst, const ObjectType* src, const int srcSize, const int numGroups) throw() 01487 // { 01488 // if (numGroups <= 1) 01489 // { 01490 // Memory::copy (dst, src, srcSize * sizeof (ObjectType)); 01491 // } 01492 // else 01493 // { 01494 // plonk_assert (srcSize % numGroups); 01495 // 01496 // const int dstSize = srcSize / numGroups; 01497 // int i, j; 01498 // 01499 // if (numGroups == 2) 01500 // { 01501 // for (i = 0; i < srcSize; ++i, ++dst, src += 2) 01502 // { 01503 // dst[0] = src[0]; 01504 // dst[dstSize] = src[1]; 01505 // } 01506 // } 01507 // else 01508 // { 01509 // for (i = 0; i < srcSize; ++i, ++dst, src += numGroups) 01510 // for (j = 0; j < numGroups; ++j) 01511 // dst[j * dstSize] = src[j]; 01512 // } 01513 // } 01514 // } 01515 01516 static void deinterleave (ObjectType* dst, const ObjectType* src, const int srcSize, const int numGroups) throw() 01517 { 01518 if (numGroups <= 1) 01519 { 01520 Memory::copy (dst, src, srcSize * sizeof (ObjectType)); 01521 } 01522 else 01523 { 01524 const int dstSize = srcSize / numGroups; 01525 int i, j; 01526 01527 for (i = 0; i < numGroups; ++i) 01528 { 01529 ObjectType* const dstTemp = dst + srcSize * i; 01530 const ObjectType* srcTemp = src + i; 01531 01532 for (j = 0; j < dstSize; ++j, srcTemp += numGroups) 01533 dstTemp[j] = *srcTemp; 01534 } 01535 } 01536 } 01537 01538 static void deinterleave (ObjectType** dst, const ObjectType* src, const int srcSize, const int numGroups) throw() 01539 { 01540 const int dstSize = srcSize / numGroups; 01541 int i, j; 01542 01543 for (i = 0; i < numGroups; ++i) 01544 { 01545 const ObjectType* srcTemp = src + i; 01546 ObjectType* const dstTemp = dst[i]; 01547 01548 for (j = 0; j < dstSize; ++j, srcTemp += numGroups) 01549 dstTemp[j] = *srcTemp; 01550 } 01551 } 01552 01553 static void interleave (ObjectType* dst, const ObjectType* src, const int srcSize, const int numGroups) throw() 01554 { 01555 if (numGroups <= 1) 01556 { 01557 Memory::copy (dst, src, srcSize * sizeof (ObjectType)); 01558 } 01559 else 01560 { 01561 const int dstSize = srcSize * numGroups; 01562 int i, j; 01563 01564 for (i = 0; i < numGroups; ++i) 01565 { 01566 ObjectType* dstTemp = dst + i; 01567 const ObjectType* const srcTemp = src + srcSize * i; 01568 01569 for (j = 0; j < dstSize; ++j, dstTemp += numGroups) 01570 *dstTemp = srcTemp[j]; 01571 } 01572 } 01573 } 01574 01575 static void interleave (ObjectType* dst, const ObjectType** src, const int srcSize, const int numGroups) throw() 01576 { 01577 const int dstSize = srcSize * numGroups; 01578 int i, j; 01579 01580 for (i = 0; i < numGroups; ++i) 01581 { 01582 ObjectType* dstTemp = dst + i; 01583 const ObjectType* const srcTemp = src[i]; 01584 01585 for (j = 0; j < dstSize; ++j, dstTemp += numGroups) 01586 *dstTemp = srcTemp[j]; 01587 } 01588 } 01589 }; 01590 01591 01592 01593 01594 #endif // PLONK_OBJECTARRAY_H