//---------------------------------------------------------------------------------------------------------------------- // // Declaration and implementation of the template class 'TC_UniqueArray' // // COPY OF ITS INSTANCES IS FORBIDDEN BY REDEFINITION OF COPY CONSTRUCTOR AND ASSIGNMENT OPERATOR. * // // This file is part of libpm library // // Copyright (C) 1997, ..., 2016 Pierre Molinaro. // // e-mail : pierre@pcmolinaro.name // // This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser 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 it will be useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANDIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // //---------------------------------------------------------------------------------------------------------------------- #pragma once //---------------------------------------------------------------------------------------------------------------------- #include "utilities/MF_Assert.h" #include "utilities/M_SourceLocation.h" #include "utilities/TF_Swap.h" #include "utilities/MF_MemoryControl.h" #include "utilities/cpp-allocation.h" //---------------------------------------------------------------------------------------------------------------------- // // Template class predeclaration // //---------------------------------------------------------------------------------------------------------------------- template class TC_UniqueArray ; //---------------------------------------------------------------------------------------------------------------------- // // swap function for TC_UniqueArray classes // //---------------------------------------------------------------------------------------------------------------------- template void swap (TC_UniqueArray & ioOperand1, TC_UniqueArray & ioOperand2) ; //---------------------------------------------------------------------------------------------------------------------- // // Template class declaration // //---------------------------------------------------------------------------------------------------------------------- template class TC_UniqueArray { //--- Default Constructor public: TC_UniqueArray (void) ; //--- Allocation Constructor (empty array) public: TC_UniqueArray (const int32_t inCapacity COMMA_LOCATION_ARGS) ; //--- Allocation Constructor (array initialized with inValue) public: TC_UniqueArray (const int32_t inCapacity, const TYPE & inValue COMMA_LOCATION_ARGS) ; //--- Virtual Destructor public: virtual ~TC_UniqueArray (void) ; //--- No copy private: TC_UniqueArray (const TC_UniqueArray &) ; private: TC_UniqueArray & operator = (const TC_UniqueArray &) ; //--- Copy public: void copyTo (TC_UniqueArray & outArray) const ; //--- Get Count public: inline int32_t count (void) const { return mCount ; } //--- Set Count To zero public: void setCountToZero (void) ; //--- Get allocated capacity public: inline int32_t capacity (void) const { return mCapacity ; } //--- Methods for setting capacity public: void setCapacity (const int32_t inNewCapacity) ; public: void setCapacityUsingSwap (const int32_t inNewCapacity) ; //--- Allocation with provided data (ioDataPtr is captured, and NULL is returned) public: void setDataFromPointer (TYPE * & ioDataPtr, const int32_t inDataLength) ; //--- Append data (inDataPtr is not released) public: void appendDataFromPointer (const TYPE * inDataPtr, const int32_t inDataLength) ; //--- Get buffer pointer public: const TYPE * unsecureBufferPointer (void) const { return mArray ; } //--- Comparisons (based on == operator on objects) public: bool operator == (const TC_UniqueArray & inOperand) const ; public: inline bool operator != (const TC_UniqueArray & inOperand) const { return ! ((*this) == inOperand) ; } //-------- Sorted array operations #ifndef DO_NOT_GENERATE_CHECKINGS private: void checkOrdered (LOCATION_ARGS) const ; #endif //--- Remove an object, suppose the array is ordered public: void removeObjectFromOrderedArray (const TYPE & inKey) ; // Test is based on 'compare' method, and inValue is copied, object is added if not already in array public: void appendUniqueObjectInOrderedArray (const TYPE & inValue) ; //--- Return -1 if not found public: int32_t indexOfObjectInOrderedArray (const TYPE & inValue) const ; //--- Intersection public: void intersectionOfOrderedArraies (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const ; //--- Union public: void unionOfOrderedArraies (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const ; //--- substract public: void substractOfOrderedArraies (const TC_UniqueArray & inSubstractedSet, TC_UniqueArray & outResult) const ; //--- Intersection (based on == operator) // Copies (using assignment operator) elements of current object that // also are in inOperand array. public: void intersectionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const ; //--- Multi set intersection (based on == operator), perserves object count. // If an object appears x times in current object and y times in operand, // it appears min (x, y) times in result. // Copies (using assignment operator) elements of current object that also are in inOperand array. public: void multiSetIntersectionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const ; //--- Union (based on == operator) // Copies (using assignment operator) elements of current object in result, // then adds elements of operand that are not yet in result. public: void unionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const ; //--- Remove all objects and deallocate public: void free (void) ; //--- Increment, decrement public: void incrementAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) ; // ++ on object public: void decrementAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) ; // -- on object //--- Append objects at the end of the array public: void appendObject (const TYPE & inValue) ; // inValue is copied public: void appendObjectIfUnique (const TYPE & inValue) ; // Test is based on == operator, and inValue is copied public: void appendObjectUsingSwap (TYPE & ioValue) ; public: void appendDefaultObjectUsingSwap (void) ; public: void appendObjects (const int32_t inCount, const TYPE & inValue) ; // inValue is copied public: void appendObjectsFromArray (const TC_UniqueArray & inObjectArray) ; // New objects are copied //--- Force entry public: void forceObjectAtIndex (const int32_t inIndex, const TYPE & inValue, const TYPE & inDefaultValue COMMA_LOCATION_ARGS) ; //--- Insert objects at index (0 <= index <= count) public: void insertObjectAtIndex (const TYPE & inValue, const int32_t inIndex COMMA_LOCATION_ARGS) ; // inValue is copied public: void insertObjectsAtIndex (const int32_t inCount, const TYPE & inValue, const int32_t inStartingIndex COMMA_LOCATION_ARGS) ; // inValue is copied public: void insertObjectUsingSwap (TYPE & ioValue, const int32_t inIndex COMMA_LOCATION_ARGS) ; public: void insertObjectsUsingExchangeAndClear (const int32_t inObjectCount, const int32_t inIndex COMMA_LOCATION_ARGS) ; //--- Find Object (uses == operator for comparing objects) // Returns -1 if not found public: int32_t indexOfFirstObjectEqualTo (const TYPE & inValue) const ; //--- Remove last object(s) public: void removeLastObject (LOCATION_ARGS) ; public: void removeLastObjects (const int32_t inCount COMMA_LOCATION_ARGS) ; //--- Exchange objects at indexes (0 <= index < count, use swap) public: void exchangeObjectAtIndexes (const int32_t inIndex1, const int32_t inIndex2 COMMA_LOCATION_ARGS) ; //--- Remove objects at index (0 <= index < count) public: void removeObjectAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) ; public: void removeObjectsAtIndex (const int32_t inCount, const int32_t inStartingIndex COMMA_LOCATION_ARGS) ; //--- Remove objects from an other array (uses == operator for selecting objects to remove) public: void removeObjectsFromArray (const TC_UniqueArray & inArray) ; // Remaining objects are copied public: void removeObjectsFromArrayUsingSwapAndClear (const TC_UniqueArray & inArray) ; // Remaining objects are copied //--- Remove identical objects (based on == operator) public: void removeIdenticalObjects (void) ; public: void removeIdenticalObjectsUsingSwapAndClear (void) ; //--- Contains an objects equal to method actual argument value (based on == operator) public: bool containsObjectEqualTo (const TYPE & inObject) const ; //--- Count objects equal to method actual argument value (based on == operator) public: int32_t countObjectsEqualTo (const TYPE & inObject) const ; //--- Count objects that respond true to function public: int32_t countObjectsThatRespondsTrueToFunction (bool (inFunction) (const TYPE & inObject)) const ; //--- Get a sub array: selection is done using a function. result array contains // objects for which inFunction returns true. // If inFunction is NULL, result array is empty. public: void subArrayUsingFunction (bool (* inFunction) (const TYPE & inObject), TC_UniqueArray & outResult) const ; //--- Sort and reverse sort array with <= and >= operators // these operators must be defined for TYPE class public: void sortArrayUsingComparisonOperators (void) ; public: void reverseSortArrayUsingComparisonOperators (void) ; //--- Sort and reverse sort array with compare method of TYPE class // inOperand1.compare (inOperand2) < 0 means inOperand1 < inOperand2 public: void sortArrayUsingCompareMethod (void) ; public: void reverseSortArrayUsingCompareMethod (void) ; //--- Sort array with a sort function (does nothing if inSortFunction == NULL) // inSortFunction (inOperand1, inOperand2) < 0 means inOperand1 < inOperand2 public: void sortArrayUsingFunction (int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) ; //--- Sort array with a sort function (does nothing if inSortFunction == NULL) // inSortFunction (inOperand1, inOperand2) < 0 means inOperand1 < inOperand2 public: void reverseSortArrayUsingFunction (int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) ; //--- Element access (with index checking) public: const TYPE lastObject (LOCATION_ARGS) const ; public: TYPE & lastObject (LOCATION_ARGS) ; public: void setObjectAtIndex (const TYPE & inObject, const int32_t inIndex COMMA_LOCATION_ARGS) ; public: TYPE & operator () (const int32_t inIndex COMMA_LOCATION_ARGS) ; public: const TYPE & operator () (const int32_t inIndex COMMA_LOCATION_ARGS) const ; //--- Private methods private: void internalSortArrayUsingOperators (const int32_t inFirst, const int32_t inLast) ; private: void internalReverseSortArrayUsingOperators (const int32_t inFirst, const int32_t inLast) ; private: void internalSortArrayUsingCompareMethod (const int32_t inFirst, const int32_t inLast) ; private: void internalReverseSortArrayUsingCompareMethod (const int32_t inFirst, const int32_t inLast) ; private: void internalSortArrayUsingFunction (const int32_t inFirst, const int32_t inLast, int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) ; private: void internalReverseSortArrayUsingFunction (const int32_t inFirst, const int32_t inLast, int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) ; //--- Index checking #ifndef DO_NOT_GENERATE_CHECKINGS protected: void checkIndex (const int32_t inIndex COMMA_LOCATION_ARGS) const ; protected: void checkIndexForInsertion (const int32_t inIndex COMMA_LOCATION_ARGS) const ; #endif //--- Protected attributes protected: TYPE * mArray ; protected: int32_t mCount ; protected: int32_t mCapacity ; //--- Array Pointer public: const TYPE * unsafeArrayPointer (void) const ; //--- swap friend void swap (TC_UniqueArray & ioOperand1, TC_UniqueArray & ioOperand2) ; } ; //---------------------------------------------------------------------------------------------------------------------- // // Default Constructor // //---------------------------------------------------------------------------------------------------------------------- template TC_UniqueArray ::TC_UniqueArray (void) : mArray ((TYPE *) NULL), mCount (0), mCapacity (0) { } //---------------------------------------------------------------------------------------------------------------------- // // Allocation Constructor // //---------------------------------------------------------------------------------------------------------------------- template TC_UniqueArray ::TC_UniqueArray (const int32_t inCapacity COMMA_LOCATION_ARGS) : mArray (NULL), mCount (0), mCapacity (0) { #ifndef DO_NOT_GENERATE_CHECKINGS MF_AssertThere (inCapacity >= 0, "inCapacity (%ld) < 0", inCapacity, 0) ; #endif if (inCapacity > 0) { macroMyNewArray (mArray, TYPE, uint32_t (inCapacity)) ; mCapacity = inCapacity ; } } //---------------------------------------------------------------------------------------------------------------------- // // Allocation Constructor // //---------------------------------------------------------------------------------------------------------------------- template TC_UniqueArray ::TC_UniqueArray (const int32_t inCapacity, const TYPE & inValue COMMA_LOCATION_ARGS) : mArray (NULL), mCount (0), mCapacity (0) { #ifndef DO_NOT_GENERATE_CHECKINGS MF_AssertThere (inCapacity >= 0, "inCapacity (%ld) < 0", inCapacity, 0) ; #endif if (inCapacity > 0) { macroMyNewArray (mArray, TYPE, uint32_t (inCapacity)) ; mCapacity = inCapacity ; for (int32_t i=0 ; i void TC_UniqueArray ::setDataFromPointer (TYPE * & ioDataPtr, const int32_t inDataLength) { macroMyDeleteArray (mArray) ; mArray = ioDataPtr ; mCount = inDataLength ; mCapacity = inDataLength ; ioDataPtr = NULL ; } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::appendDataFromPointer (const TYPE * inDataPtr, const int32_t inDataLength) { for (int32_t i=0 ; i TC_UniqueArray ::~TC_UniqueArray (void) { macroMyDeleteArray (mArray) ; } //---------------------------------------------------------------------------------------------------------------------- // // Destructor // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::setCountToZero (void) { mCount = 0 ; } //---------------------------------------------------------------------------------------------------------------------- // // Method for making room using copy // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::copyTo (TC_UniqueArray & outArray) const { outArray.setCountToZero () ; for (int32_t i=0 ; i void TC_UniqueArray ::setCapacity (const int32_t inNewCapacity) { if (mCapacity < inNewCapacity) { int32_t newCapacity = (mCapacity > 32) ? mCapacity : 32 ; while (newCapacity < inNewCapacity) { newCapacity <<= 1 ; } TYPE * newArray = NULL ; macroMyNewArray (newArray, TYPE, uint32_t (newCapacity)) ; for (int32_t i=0 ; i void TC_UniqueArray ::forceObjectAtIndex (const int32_t inIndex, const TYPE & inValue, const TYPE & inDefaultValue COMMA_LOCATION_ARGS) { if (mCapacity <= inIndex) { int32_t newCapacity = (mCapacity > 32) ? mCapacity : 32 ; while (newCapacity <= inIndex) { newCapacity <<= 1 ; } TYPE * newArray = NULL ; macroMyNewArrayThere (newArray, TYPE, uint32_t (newCapacity)) ; for (int32_t i=0 ; i void TC_UniqueArray ::setCapacityUsingSwap (const int32_t inNewCapacity) { if (mCapacity < inNewCapacity) { int32_t newCapacity = (mCapacity > 32) ? mCapacity : 32 ; while (newCapacity < inNewCapacity) { newCapacity <<= 1 ; } TYPE * newArray = NULL ; macroMyNewArray (newArray, TYPE, uint32_t (newCapacity)) ; for (int32_t i=0 ; i void TC_UniqueArray ::free (void) { mCount = 0 ; macroMyDeleteArray (mArray) ; mCapacity = 0 ; } //---------------------------------------------------------------------------------------------------------------------- // // Add object at the end of the array // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::appendObject (const TYPE & inValue) { if (mCount >= mCapacity) { setCapacity (mCount + 1 + mCount / 2) ; } mArray [mCount] = inValue ; mCount ++ ; } //---------------------------------------------------------------------------------------------------------------------- // // Add object at the end of the array, if object is not already in array // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::appendObjectIfUnique (const TYPE & inValue) { bool found = false ; for (int32_t i=0 ; (i void TC_UniqueArray ::appendObjects (const int32_t inCount, const TYPE & inValue) { if (inCount > 0) { const int32_t newCount = mCount + inCount ; setCapacity (newCount) ; for (int32_t i=mCount ; i void TC_UniqueArray ::appendObjectUsingSwap (TYPE & ioValue) { setCapacityUsingSwap (mCount + 1) ; swap (mArray [mCount], ioValue) ; mCount ++ ; } //---------------------------------------------------------------------------------------------------------------------- // // Add default object at the end of the array // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::appendDefaultObjectUsingSwap (void) { setCapacityUsingSwap (mCount + 1) ; TYPE value ; swap (mArray [mCount], value) ; mCount ++ ; } //---------------------------------------------------------------------------------------------------------------------- // // Add objects at the end of the array from an other array // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::appendObjectsFromArray (const TC_UniqueArray & inObjectArray) { if (inObjectArray.mCount > 0) { setCapacity (mCount + inObjectArray.mCount) ; for (int32_t i=0 ; i void TC_UniqueArray ::checkIndexForInsertion (const int32_t inIndex COMMA_LOCATION_ARGS) const { MF_AssertThere (inIndex >= 0, "inIndex (%ld) < 0", inIndex, 0) ; MF_AssertThere (inIndex <= mCount, "inIndex (%d) > mCount (%ld)", inIndex, mCount) ; } #endif //---------------------------------------------------------------------------------------------------------------------- // // Insert object at index // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::insertObjectAtIndex (const TYPE & inValue, const int32_t inIndex COMMA_LOCATION_ARGS) { // inValue is copied #ifndef DO_NOT_GENERATE_CHECKINGS checkIndexForInsertion (inIndex COMMA_THERE) ; #endif setCapacity (mCount + 1) ; for (int32_t i=mCount ; i>inIndex ; i--) { mArray [i] = mArray [i-1] ; } mArray [inIndex] = inValue ; mCount ++ ; } //---------------------------------------------------------------------------------------------------------------------- // // Insert objects at index // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::insertObjectsAtIndex (const int32_t inCount, const TYPE & inValue, const int32_t inStartingIndex COMMA_LOCATION_ARGS) { // inValue is copied if (inCount > 0) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndexForInsertion (inStartingIndex COMMA_THERE) ; #endif setCapacity (mCount + inCount) ; for (int32_t i=mCount+inCount-1 ; i>=(inStartingIndex + inCount) ; i--) { mArray [i] = mArray [i-inCount] ; } for (int32_t i=0 ; i void TC_UniqueArray :: insertObjectUsingSwap (TYPE & ioValue, const int32_t inIndex COMMA_LOCATION_ARGS) { // inValue is copied #ifndef DO_NOT_GENERATE_CHECKINGS checkIndexForInsertion (inIndex COMMA_THERE) ; #endif setCapacity (mCount + 1) ; for (int32_t i=mCount ; i>inIndex ; i--) { swap (mArray [i], mArray [i-1]) ; } swap (mArray [inIndex], ioValue) ; mCount ++ ; } //---------------------------------------------------------------------------------------------------------------------- // // Insert objects at index using default constructor // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray :: insertObjectsUsingExchangeAndClear (const int32_t inCount, const int32_t inStartingIndex COMMA_LOCATION_ARGS) { // inValue is copied if (inCount > 0) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndexForInsertion (inStartingIndex COMMA_THERE) ; #endif setCapacity (mCount + inCount) ; for (int32_t i=mCount+inCount-1 ; i>=(inStartingIndex + inCount) ; i--) { swap (mArray [i], mArray [i-inCount]) ; } for (int32_t i=0 ; i void TC_UniqueArray ::removeLastObject (LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (mCount-1 COMMA_THERE) ; #endif mCount -- ; } //---------------------------------------------------------------------------------------------------------------------- // // remove last objects // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::removeLastObjects (const int32_t inCount COMMA_LOCATION_ARGS) { if (inCount > 0) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (mCount-inCount COMMA_THERE) ; #endif mCount -= inCount ; } } //---------------------------------------------------------------------------------------------------------------------- // // remove object at index (0 <= index < count) // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::exchangeObjectAtIndexes (const int32_t inIndex1, const int32_t inIndex2 COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex1 COMMA_THERE) ; checkIndex (inIndex2 COMMA_THERE) ; #endif if (inIndex1 != inIndex2) { swap (mArray [inIndex1], mArray [inIndex2]) ; } } //---------------------------------------------------------------------------------------------------------------------- // // remove object at index (0 <= index < count) // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::removeObjectAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif for (int32_t i=inIndex+1 ; i< mCount ; i++) { mArray [i-1] = mArray [i] ; } mCount -- ; } //---------------------------------------------------------------------------------------------------------------------- // // delete objects from index (0<=index void TC_UniqueArray :: removeObjectsAtIndex (const int32_t inCount, const int32_t inStartingIndex COMMA_LOCATION_ARGS) { if (inCount > 0) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inStartingIndex COMMA_THERE) ; checkIndexForInsertion (inStartingIndex+inCount COMMA_THERE) ; #endif for (int32_t i=inStartingIndex+inCount ; i int32_t TC_UniqueArray ::indexOfFirstObjectEqualTo (const TYPE & inValue) const { int32_t result = -1 ; for (int32_t i=0 ; (i void TC_UniqueArray ::checkIndex (const int32_t inIndex COMMA_LOCATION_ARGS) const { MF_AssertThere (inIndex >= 0, "inIndex (%lld) < 0", inIndex, 0) ; MF_AssertThere (inIndex < mCount, "inIndex (%lld) >= mCount (%lld)", inIndex, mCount) ; } #endif //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::setObjectAtIndex (const TYPE & inObject, const int32_t inIndex COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif if (NULL != mArray) { mArray [inIndex] = inObject ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::incrementAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif mArray [inIndex] ++ ; } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::decrementAtIndex (const int32_t inIndex COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif mArray [inIndex] -- ; } //---------------------------------------------------------------------------------------------------------------------- template TYPE & TC_UniqueArray ::operator () (const int32_t inIndex COMMA_LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif return mArray [inIndex] ; } //---------------------------------------------------------------------------------------------------------------------- template const TYPE & TC_UniqueArray :: operator () (const int32_t inIndex COMMA_LOCATION_ARGS) const { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (inIndex COMMA_THERE) ; #endif return mArray [inIndex] ; } //---------------------------------------------------------------------------------------------------------------------- template const TYPE TC_UniqueArray ::lastObject (LOCATION_ARGS) const { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (mCount-1 COMMA_THERE) ; #endif return mArray [mCount-1] ; } //---------------------------------------------------------------------------------------------------------------------- template TYPE & TC_UniqueArray ::lastObject (LOCATION_ARGS) { #ifndef DO_NOT_GENERATE_CHECKINGS checkIndex (mCount-1 COMMA_THERE) ; #endif return mArray [mCount-1] ; } //---------------------------------------------------------------------------------------------------------------------- // // Extract sub array // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray :: subArrayUsingFunction (bool (* inFunction) (const TYPE & inObject), TC_UniqueArray & outResult) const { outResult.clear () ; if (inFunction != NULL) { outResult.setCapacity (mCount) ; for (int32_t i=0 ; i= and <= operators // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::internalSortArrayUsingOperators (const int32_t inFirst, const int32_t inLast) { //--- Sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (mArray [i] <= mArray [inFirst])) { i ++ ; } while ((j > inFirst) && (mArray [j] >= mArray [inFirst])) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalSortArrayUsingOperators (inFirst, j-1) ; internalSortArrayUsingOperators (j+1, inLast) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::sortArrayUsingComparisonOperators (void) { internalSortArrayUsingOperators (0, mCount - 1) ; } //---------------------------------------------------------------------------------------------------------------------- // // Reverse sort array using >= and <= operators // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::internalReverseSortArrayUsingOperators (const int32_t inFirst, const int32_t inLast) { //--- Reverse sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (mArray [i] >= mArray [inFirst])) { i ++ ; } while ((j > inFirst) && (mArray [j] <= mArray [inFirst])) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalReverseSortArrayUsingOperators (inFirst, j-1) ; internalReverseSortArrayUsingOperators (j+1, inLast) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::reverseSortArrayUsingComparisonOperators (void) { internalReverseSortArrayUsingOperators (0, mCount - 1) ; } //---------------------------------------------------------------------------------------------------------------------- // // Sort array using comare method // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::internalSortArrayUsingCompareMethod (const int32_t inFirst, const int32_t inLast) { //--- Sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (mArray [i].compare (mArray [inFirst]) <= 0)) { i ++ ; } while ((j > inFirst) && (mArray [j].compare (mArray [inFirst]) >= 0)) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalSortArrayUsingCompareMethod (inFirst, j-1) ; internalSortArrayUsingCompareMethod (j+1, inLast) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::sortArrayUsingCompareMethod (void) { internalSortArrayUsingCompareMethod (0, mCount - 1) ; } //---------------------------------------------------------------------------------------------------------------------- // // Reverse sort array using compare method // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray:: internalReverseSortArrayUsingCompareMethod (const int32_t inFirst, const int32_t inLast) { //--- Reverse sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (mArray [i].compare (mArray [inFirst]) >= 0)) { i ++ ; } while ((j > inFirst) && (mArray [j].compare (mArray [inFirst]) <= 0)) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalReverseSortArrayUsingCompareMethod (inFirst, j-1) ; internalReverseSortArrayUsingCompareMethod (j+1, inLast) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray::reverseSortArrayUsingCompareMethod (void) { internalReverseSortArrayUsingCompareMethod (0, mCount - 1) ; } //---------------------------------------------------------------------------------------------------------------------- // // Sort array using comparison function // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray:: internalSortArrayUsingFunction (const int32_t inFirst, const int32_t inLast, int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) { //--- Sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (inSortFunction (mArray [i], mArray [inFirst]) <= 0)) { i ++ ; } while ((j > inFirst) && (inSortFunction (mArray [j], mArray [inFirst]) >= 0)) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalSortArrayUsingFunction (inFirst, j-1, inSortFunction) ; internalSortArrayUsingFunction (j+1, inLast, inSortFunction) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray:: sortArrayUsingFunction (int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) { if (inSortFunction != NULL) { internalSortArrayUsingFunction (0, mCount - 1, inSortFunction) ; } } //---------------------------------------------------------------------------------------------------------------------- // // Reverse sort array using comparison function // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray:: internalReverseSortArrayUsingFunction (const int32_t inFirst, const int32_t inLast, int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) { //--- Reverse sort using 'quick sort' algorithm if (inFirst < inLast) { int32_t i = inFirst ; int32_t j = inLast ; while (i < j) { while ((i < inLast) && (inSortFunction (mArray [i], mArray [inFirst]) >= 0)) { i ++ ; } while ((j > inFirst) && (inSortFunction (mArray [j], mArray [inFirst]) <= 0)) { j -- ; } if (i < j) { swap (mArray [i], mArray [j]) ; } } swap (mArray [j], mArray [inFirst]) ; internalReverseSortArrayUsingFunction (inFirst, j-1, inSortFunction) ; internalReverseSortArrayUsingFunction (j+1, inLast, inSortFunction) ; } } //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray :: reverseSortArrayUsingFunction (int32_t (* inSortFunction) (const TYPE & inOperand1, const TYPE & inOperand2)) { if (inSortFunction != NULL) { internalReverseSortArrayUsingFunction (0, mCount - 1, inSortFunction) ; } } //---------------------------------------------------------------------------------------------------------------------- // // Comparisons (based on == operator on objects) // //---------------------------------------------------------------------------------------------------------------------- template bool TC_UniqueArray::operator == (const TC_UniqueArray & inOperand) const { bool areEqual = mCount == inOperand.mCount ; for (int32_t i=0 ; (i void TC_UniqueArray ::removeObjectsFromArray (const TC_UniqueArray & inArray) { int32_t sourceIndex = 0 ; int32_t targetIndex = 0 ; while (sourceIndex < mCount) { //--- Serach for element bool found = false ; for (int32_t i=0 ; (i void TC_UniqueArray :: removeObjectsFromArrayUsingSwapAndClear (const TC_UniqueArray & inArray) { int32_t sourceIndex = 0 ; int32_t targetIndex = 0 ; while (sourceIndex < mCount) { //--- Serach for element bool found = false ; for (int32_t i=0 ; (i void TC_UniqueArray ::removeIdenticalObjects (void) { int32_t sourceIndex = 1 ; int32_t targetIndex = 1 ; while (sourceIndex < mCount) { bool found = false ; for (int32_t i=0 ; (i void TC_UniqueArray ::removeIdenticalObjectsUsingSwapAndClear (void) { int32_t sourceIndex = 1 ; int32_t targetIndex = 1 ; while (sourceIndex < mCount) { bool found = false ; for (int32_t i=0 ; (i bool TC_UniqueArray ::containsObjectEqualTo (const TYPE & inObject) const { bool hasObject = false ; for (int32_t i=0 ; (i int32_t TC_UniqueArray ::countObjectsEqualTo (const TYPE & inObject) const { int32_t matchCount = 0 ; for (int32_t i=0 ; i int32_t TC_UniqueArray :: countObjectsThatRespondsTrueToFunction (bool (inFunction) (const TYPE & inObject)) const { int32_t matchCount = 0 ; if (inFunction != NULL) { for (int32_t i=0 ; i void TC_UniqueArray :: intersectionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const { //--- Empty destination array outResult.clear () ; outResult.setCapacity (mCount) ; //--- loop throught array for (int32_t i=0 ; ivoid TC_UniqueArray :: multiSetIntersectionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const { //--- Empty destination array outResult.clear () ; outResult.setCapacity (mCount) ; //--- Build counted set for current object TC_UniqueArray set (mCount COMMA_HERE) ; TC_UniqueArray setCount (mCount COMMA_HERE) ; for (int32_t i=0 ; i void TC_UniqueArray ::unionWithArray (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const { //--- Empty destination array outResult.clear () ; outResult.setCapacity (mCount + inOperand.mCount) ; //--- Copy current object for (int32_t i=0 ; i const TYPE * TC_UniqueArray ::unsafeArrayPointer (void) const { return mArray ; } //---------------------------------------------------------------------------------------------------------------------- // // swap function for TC_UniqueArray classes // //---------------------------------------------------------------------------------------------------------------------- template void swap (TC_UniqueArray & ioOperand1, TC_UniqueArray & ioOperand2) { swap (ioOperand1.mCount, ioOperand2.mCount) ; swap (ioOperand1.mCapacity, ioOperand2.mCapacity) ; swap (ioOperand1.mArray, ioOperand2.mArray) ; } //---------------------------------------------------------------------------------------------------------------------- // // Add object in array, maintaining array sorted // //---------------------------------------------------------------------------------------------------------------------- #ifndef DO_NOT_GENERATE_CHECKINGS template void TC_UniqueArray ::checkOrdered (LOCATION_ARGS) const { for (int32_t i=1 ; i void TC_UniqueArray ::appendUniqueObjectInOrderedArray (const TYPE & inKey) { //--- Search bool found = false ; int32_t low = 0 ; int32_t high = mCount - 1 ; int32_t idx = 0 ; int32_t r = 0 ; while ((low <= high) && ! found) { idx = (low + high) / 2 ; r = mArray [idx].compare (inKey) ; if (r < 0) { low = idx + 1 ; }else if (r > 0) { high = idx - 1 ; }else{ found = true ; } } //--- Insert in not found if (! found) { setCapacity (mCount + 1) ; idx += r < 0 ; for (int32_t i=mCount ; i>idx ; i--) { mArray [i] = mArray [i - 1] ; } mArray [idx] = inKey ; mCount ++ ; } //--- Check array is ordered #ifndef DO_NOT_GENERATE_CHECKINGS checkOrdered (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- // // indexOfObjectInOrderedArray // //---------------------------------------------------------------------------------------------------------------------- template int32_t TC_UniqueArray ::indexOfObjectInOrderedArray (const TYPE & inValue) const { //--- Search bool found = false ; int32_t low = 0 ; int32_t high = mCount - 1 ; int32_t idx = 0 ; int32_t r = 0 ; while ((low <= high) && ! found) { idx = (low + high) / 2 ; r = mArray [idx].compare (inValue) ; if (r < 0) { low = idx + 1 ; }else if (r > 0) { high = idx - 1 ; }else{ found = true ; } } return found ? idx : -1 ; } //---------------------------------------------------------------------------------------------------------------------- // // intersectionOfOrderedArraies // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::intersectionOfOrderedArraies (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const { outResult.setCountToZero () ; int32_t leftIdx = 0 ; int32_t rightIdx = 0 ; while ((leftIdx < count ()) && (rightIdx < inOperand.count ())) { const int32_t r = (*this) (leftIdx COMMA_HERE).compare (inOperand (rightIdx COMMA_HERE)) ; if (r < 0) { leftIdx ++ ; }else if (r > 0) { rightIdx ++ ; }else{ outResult.appendObject (inOperand (rightIdx COMMA_HERE)) ; leftIdx ++ ; rightIdx ++ ; } } #ifndef DO_NOT_GENERATE_CHECKINGS outResult.checkOrdered (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- // // unionOfOrderedArraies // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::unionOfOrderedArraies (const TC_UniqueArray & inOperand, TC_UniqueArray & outResult) const { outResult.setCountToZero () ; int32_t leftIdx = 0 ; int32_t rightIdx = 0 ; while ((leftIdx < count ()) && (rightIdx < inOperand.count ())) { const int32_t r = (*this) (leftIdx COMMA_HERE).compare (inOperand (rightIdx COMMA_HERE)) ; if (r < 0) { outResult.appendObject ((*this) (leftIdx COMMA_HERE)) ; leftIdx ++ ; }else if (r > 0) { outResult.appendObject (inOperand (rightIdx COMMA_HERE)) ; rightIdx ++ ; }else{ outResult.appendObject (inOperand (rightIdx COMMA_HERE)) ; leftIdx ++ ; rightIdx ++ ; } } while (leftIdx < count ()) { outResult.appendObject ((*this) (leftIdx COMMA_HERE)) ; leftIdx ++ ; } while (rightIdx < inOperand.count ()) { outResult.appendObject (inOperand (rightIdx COMMA_HERE)) ; rightIdx ++ ; } #ifndef DO_NOT_GENERATE_CHECKINGS outResult.checkOrdered (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- // // substractOfOrderedArraies // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::substractOfOrderedArraies (const TC_UniqueArray & inSubstractedSet, TC_UniqueArray & outResult) const { outResult.setCountToZero () ; int32_t leftIdx = 0 ; int32_t rightIdx = 0 ; while ((leftIdx < count ()) && (rightIdx < inSubstractedSet.count ())) { const int32_t r = (*this) (leftIdx COMMA_HERE).compare (inSubstractedSet (rightIdx COMMA_HERE)) ; if (r < 0) { outResult.appendObject ((*this) (leftIdx COMMA_HERE)) ; leftIdx ++ ; }else if (r > 0) { rightIdx ++ ; }else{ leftIdx ++ ; rightIdx ++ ; } } while (leftIdx < count ()) { outResult.appendObject ((*this) (leftIdx COMMA_HERE)) ; leftIdx ++ ; } #ifndef DO_NOT_GENERATE_CHECKINGS outResult.checkOrdered (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- // // Remove object in ordered array (based on < and > operators) // //---------------------------------------------------------------------------------------------------------------------- template void TC_UniqueArray ::removeObjectFromOrderedArray (const TYPE & inKey) { bool found = false ; int32_t low = 0 ; int32_t high = mCount - 1 ; while ((low <= high) && !found) { const int32_t mid = (low + high) / 2 ; const TYPE x = mArray [mid] ; const int32_t r = x.compare (inKey) ; if (r < 0) { low = mid + 1 ; }else if (r > 0) { high = mid - 1 ; }else{ found = true ; removeObjectAtIndex (mid COMMA_HERE) ; } } #ifndef DO_NOT_GENERATE_CHECKINGS checkOrdered (HERE) ; #endif } //----------------------------------------------------------------------------------------------------------------------