diff --git a/source/modules/water/Makefile b/source/modules/water/Makefile index df36bfc0f..49202242f 100644 --- a/source/modules/water/Makefile +++ b/source/modules/water/Makefile @@ -129,6 +129,7 @@ $(OBJDIR)/$(MODULENAME).mm.%64.o: $(MODULENAME).cpp # ---------------------------------------------------------------------------------------------------------------------------- -include $(OBJS:%.o=%.d) +-include $(OBJS_files:%.o=%.d) -include $(OBJS_posix32:%.o=%.d) -include $(OBJS_posix64:%.o=%.d) -include $(OBJS_win32:%.o=%.d) diff --git a/source/modules/water/containers/Array.h b/source/modules/water/containers/Array.h index 51be67922..66fcd395a 100644 --- a/source/modules/water/containers/Array.h +++ b/source/modules/water/containers/Array.h @@ -3,7 +3,7 @@ This file is part of the Water library. Copyright (c) 2016 ROLI Ltd. - Copyright (C) 2017 Filipe Coelho + Copyright (C) 2017-2018 Filipe Coelho Permission is granted to use this software under the terms of the ISC license http://www.isc.org/downloads/software-support-policy/isc-license/ @@ -416,7 +416,7 @@ public: const int numberToMove = numUsed - indexToInsertAt; if (numberToMove > 0) - std::memmove (insertPos + 1, insertPos, ((size_t) numberToMove) * sizeof (ElementType)); + data.moveMemory (insertPos + 1, insertPos, numberToMove); new (insertPos) ElementType (newElement); ++numUsed; @@ -441,19 +441,21 @@ public: @param numberOfTimesToInsertIt how many copies of the value to insert @see insert, add, addSorted, set */ - void insertMultiple (int indexToInsertAt, ParameterType newElement, + bool insertMultiple (int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt) { if (numberOfTimesToInsertIt > 0) { - data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt); + if (! data.ensureAllocatedSize (numUsed + numberOfTimesToInsertIt)) + return false; + ElementType* insertPos; if (isPositiveAndBelow (indexToInsertAt, numUsed)) { insertPos = data.elements + indexToInsertAt; const int numberToMove = numUsed - indexToInsertAt; - memmove (insertPos + numberOfTimesToInsertIt, insertPos, ((size_t) numberToMove) * sizeof (ElementType)); + data.moveMemory (insertPos + numberOfTimesToInsertIt, insertPos, numberToMove); } else { @@ -469,8 +471,11 @@ public: // new statement to avoid a compiler bug in VS2014 } } + + return true; } +#if 0 /** Inserts an array of values into this array at a given position. If the index is less than 0 or greater than the size of the array, the @@ -483,20 +488,22 @@ public: @param numberOfElements how many items are in the array @see insert, add, addSorted, set */ - void insertArray (int indexToInsertAt, + bool insertArray (int indexToInsertAt, const ElementType* newElements, int numberOfElements) { if (numberOfElements > 0) { - data.ensureAllocatedSize (numUsed + numberOfElements); + if (! data.ensureAllocatedSize (numUsed + numberOfElements)) + return false; + ElementType* insertPos = data.elements; if (isPositiveAndBelow (indexToInsertAt, numUsed)) { insertPos += indexToInsertAt; const int numberToMove = numUsed - indexToInsertAt; - memmove (insertPos + numberOfElements, insertPos, (size_t) numberToMove * sizeof (ElementType)); + std::memmove (insertPos + numberOfElements, insertPos, (size_t) numberToMove * sizeof (ElementType)); } else { @@ -508,7 +515,10 @@ public: while (--numberOfElements >= 0) new (insertPos++) ElementType (*newElements++); } + + return true; } +#endif /** Appends a new element at the end of the array as long as the array doesn't already contain it. @@ -903,7 +913,7 @@ public: const int numToShift = numUsed - endIndex; if (numToShift > 0) - memmove (e, e + numberToRemove, ((size_t) numToShift) * sizeof (ElementType)); + data.moveMemory (e, e + numberToRemove, numToShift); numUsed -= numberToRemove; minimiseStorageAfterRemoval(); @@ -994,50 +1004,6 @@ public: } } - /** Moves one of the values to a different position. - - This will move the value to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the value to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this value to end up. If this - is less than zero, the value will be moved to the end - of the array - */ - void move (const int currentIndex, int newIndex) noexcept - { - if (currentIndex != newIndex) - { - if (isPositiveAndBelow (currentIndex, numUsed)) - { - if (! isPositiveAndBelow (newIndex, numUsed)) - newIndex = numUsed - 1; - - char tempCopy [sizeof (ElementType)]; - memcpy (tempCopy, data.elements + currentIndex, sizeof (ElementType)); - - if (newIndex > currentIndex) - { - memmove (data.elements + currentIndex, - data.elements + currentIndex + 1, - sizeof (ElementType) * (size_t) (newIndex - currentIndex)); - } - else - { - memmove (data.elements + newIndex + 1, - data.elements + newIndex, - sizeof (ElementType) * (size_t) (currentIndex - newIndex)); - } - - memcpy (data.elements + newIndex, tempCopy, sizeof (ElementType)); - } - } - } - //============================================================================== /** Reduces the amount of storage being used by the array. @@ -1120,7 +1086,7 @@ private: const int numberToShift = numUsed - indexToRemove; if (numberToShift > 0) - memmove (e, e + 1, ((size_t) numberToShift) * sizeof (ElementType)); + data.moveMemory (e, e + 1, numberToShift); minimiseStorageAfterRemoval(); } diff --git a/source/modules/water/containers/ArrayAllocationBase.h b/source/modules/water/containers/ArrayAllocationBase.h index 6f56ba563..7a79bca23 100644 --- a/source/modules/water/containers/ArrayAllocationBase.h +++ b/source/modules/water/containers/ArrayAllocationBase.h @@ -3,7 +3,7 @@ This file is part of the Water library. Copyright (c) 2016 ROLI Ltd. - Copyright (C) 2017 Filipe Coelho + Copyright (C) 2017-2018 Filipe Coelho Permission is granted to use this software under the terms of the ISC license http://www.isc.org/downloads/software-support-policy/isc-license/ @@ -44,6 +44,29 @@ namespace water { template class ArrayAllocationBase { +#if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS +private: + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 + template + struct IsTriviallyCopyable : std::integral_constant {}; + #else + template + using IsTriviallyCopyable = std::is_trivially_copyable; + #endif + + template + using TriviallyCopyableVoid = typename std::enable_if::value, void>::type; + + template + using TriviallyCopyableBool = typename std::enable_if::value, bool>::type; + + template + using NonTriviallyCopyableVoid = typename std::enable_if::value, void>::type; + + template + using NonTriviallyCopyableBool = typename std::enable_if::value, bool>::type; +#endif // WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS + public: //============================================================================== /** Creates an empty array. */ @@ -60,9 +83,7 @@ public: #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS ArrayAllocationBase (ArrayAllocationBase&& other) noexcept : elements (static_cast&&> (other.elements)), - numAllocated (other.numAllocated) - { - } + numAllocated (other.numAllocated) {} ArrayAllocationBase& operator= (ArrayAllocationBase&& other) noexcept { @@ -78,27 +99,72 @@ public: This will retain any data currently held in the array, and either add or remove extra space at the end. - @param numElements the number of elements that are needed + @param numNewElements the number of elements that are needed */ - bool setAllocatedSize (const int numElements) noexcept + #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS + template TriviallyCopyableBool + #else + bool + #endif + setAllocatedSize (const int numNewElements) noexcept + { + if (numAllocated != numNewElements) + { + if (numNewElements > 0) + { + if (! elements.realloc ((size_t) numNewElements)) + return false; + } + else + { + elements.free(); + } + + numAllocated = numNewElements; + } + + return true; + } + + #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS + template + NonTriviallyCopyableBool setAllocatedSize (const int numNewElements) noexcept { - if (numAllocated != numElements) + if (numAllocated != numNewElements) { - if (numElements > 0) + if (numNewElements > 0) { - if (! elements.realloc ((size_t) numElements)) + HeapBlock newElements; + + if (! newElements.malloc (numNewElements)) return false; + + for (int i = 0; i < numNewElements; ++i) + { + if (i < numAllocated) + { + new (newElements + i) ElementType (std::move (elements[i])); + elements[i].~ElementType(); + } + else + { + new (newElements + i) ElementType (); + } + } + + elements = std::move (newElements); } else { elements.free(); } - numAllocated = numElements; + numAllocated = numNewElements; } return true; } + #endif /** Increases the amount of storage allocated if it is less than a given amount. @@ -134,6 +200,57 @@ public: std::swap (numAllocated, other.numAllocated); } + #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS + template TriviallyCopyableVoid + #else + void + #endif + moveMemory (ElementType* target, const ElementType* source, const int numElements) noexcept + { + CARLA_SAFE_ASSERT_RETURN(target != nullptr,); + CARLA_SAFE_ASSERT_RETURN(source != nullptr,); + CARLA_SAFE_ASSERT_RETURN(target != source,); + CARLA_SAFE_ASSERT_RETURN(numElements > 0,); + + std::memmove (target, source, ((size_t) numElements) * sizeof (ElementType)); + } + + #if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS + template + NonTriviallyCopyableVoid moveMemory (ElementType* target, const ElementType* source, const int numElements) noexcept + { + CARLA_SAFE_ASSERT_RETURN(target != nullptr,); + CARLA_SAFE_ASSERT_RETURN(source != nullptr,); + CARLA_SAFE_ASSERT_RETURN(target != source,); + CARLA_SAFE_ASSERT_RETURN(numElements > 0,); + + if (target > source) + { + for (int i = numElements; --i >= 0;) + { + moveElement (target, std::move (*source)); + ++target; + ++source; + } + } + else + { + for (int i = numElements; --i >= 0;) + { + moveElement (target, std::move (*source)); + --target; + --source; + } + } + } + + void moveElement (ElementType* destination, const ElementType&& source) + { + destination->~ElementType(); + new (destination) ElementType (std::move (source)); + } + #endif + //============================================================================== HeapBlock elements; int numAllocated; diff --git a/source/modules/water/text/StringArray.cpp b/source/modules/water/text/StringArray.cpp index e06875bb3..530610123 100644 --- a/source/modules/water/text/StringArray.cpp +++ b/source/modules/water/text/StringArray.cpp @@ -199,11 +199,6 @@ int StringArray::indexOf (StringRef stringToLookFor, const bool ignoreCase, int return -1; } -void StringArray::move (const int currentIndex, const int newIndex) noexcept -{ - strings.move (currentIndex, newIndex); -} - //============================================================================== void StringArray::remove (const int index) { diff --git a/source/modules/water/text/StringArray.h b/source/modules/water/text/StringArray.h index 70944384f..57ed5d300 100644 --- a/source/modules/water/text/StringArray.h +++ b/source/modules/water/text/StringArray.h @@ -325,22 +325,6 @@ public: */ void removeEmptyStrings (bool removeWhitespaceStrings = true); - /** Moves one of the strings to a different position. - - This will move the string to a specified index, shuffling along - any intervening elements as required. - - So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling - move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }. - - @param currentIndex the index of the value to be moved. If this isn't a - valid index, then nothing will be done - @param newIndex the index at which you'd like this value to end up. If this - is less than zero, the value will be moved to the end - of the array - */ - void move (int currentIndex, int newIndex) noexcept; - /** Deletes any whitespace characters from the starts and ends of all the strings. */ void trim();