49 template <
class OtherElementType,
class OtherCriticalSection>
50 using AllowConversion =
typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>,
51 std::tuple<OtherElementType, OtherCriticalSection>>::value>::type;
63 : elements (std::move (
other.elements)),
64 numAllocated (
other.numAllocated),
65 numUsed (
other.numUsed)
67 other.numAllocated = 0;
91 : elements (std::move (
other.elements)),
92 numAllocated (
other.numAllocated),
93 numUsed (
other.numUsed)
95 other.numAllocated = 0;
110 elements = std::move (
other.elements);
111 numAllocated =
other.numAllocated;
112 numUsed =
other.numUsed;
114 other.numAllocated = 0;
121 template <
class OtherArrayType>
136 template <
class OtherArrayType>
137 bool operator!= (
const OtherArrayType& other)
const noexcept
139 return ! operator== (other);
143 inline ElementType& operator[] (
const int index)
const noexcept
145 jassert (elements !=
nullptr);
146 jassert (isPositiveAndBelow (index, numUsed));
147 return elements[index];
150 inline ElementType getValueWithDefault (
const int index)
const noexcept
152 return isPositiveAndBelow (index, numUsed) ? elements[index] : ElementType();
155 inline ElementType getFirst() const noexcept
157 return numUsed > 0 ? elements[0] : ElementType();
160 inline ElementType getLast() const noexcept
162 return numUsed > 0 ? elements[numUsed - 1] : ElementType();
166 inline ElementType* begin() const noexcept
171 inline ElementType* end() const noexcept
173 return elements + numUsed;
176 inline ElementType* data() const noexcept
181 inline int size() const noexcept
186 inline int capacity() const noexcept
192 void setAllocatedSize (
int numElements)
194 jassert (numElements >= numUsed);
196 if (numAllocated != numElements)
199 setAllocatedSizeInternal (numElements);
204 numAllocated = numElements;
207 void ensureAllocatedSize (
int minNumElements)
209 if (minNumElements > numAllocated)
210 setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
212 jassert (numAllocated <= 0 || elements !=
nullptr);
215 void shrinkToNoMoreThan (
int maxNumElements)
217 if (maxNumElements < numAllocated)
218 setAllocatedSize (maxNumElements);
223 for (
int i = 0; i < numUsed; ++i)
224 elements[i].~ElementType();
230 void swapWith (ArrayBase& other)
noexcept
233 std::swap (numAllocated, other.numAllocated);
234 std::swap (numUsed, other.numUsed);
238 void add (
const ElementType& newElement)
240 checkSourceIsNotAMember (&newElement);
241 ensureAllocatedSize (numUsed + 1);
242 addAssumingCapacityIsReady (newElement);
245 void add (ElementType&& newElement)
247 checkSourceIsNotAMember (&newElement);
248 ensureAllocatedSize (numUsed + 1);
249 addAssumingCapacityIsReady (std::move (newElement));
252 template <
typename... OtherElements>
253 void add (
const ElementType& firstNewElement, OtherElements... otherElements)
255 checkSourceIsNotAMember (&firstNewElement);
256 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
257 addAssumingCapacityIsReady (firstNewElement, otherElements...);
260 template <
typename... OtherElements>
261 void add (ElementType&& firstNewElement, OtherElements... otherElements)
263 checkSourceIsNotAMember (&firstNewElement);
264 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
265 addAssumingCapacityIsReady (std::move (firstNewElement), otherElements...);
269 template <
typename Type>
270 void addArray (
const Type* elementsToAdd,
int numElementsToAdd)
272 ensureAllocatedSize (numUsed + numElementsToAdd);
273 addArrayInternal (elementsToAdd, numElementsToAdd);
274 numUsed += numElementsToAdd;
277 template <
typename TypeToCreateFrom>
278 void addArray (
const std::initializer_list<TypeToCreateFrom>& items)
280 ensureAllocatedSize (numUsed + (
int) items.size());
282 for (
auto& item : items)
283 new (elements + numUsed++) ElementType (item);
286 template <
class OtherArrayType>
287 void addArray (
const OtherArrayType& arrayToAddFrom)
289 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
290 ensureAllocatedSize (numUsed + (
int) arrayToAddFrom.size());
292 for (
auto& e : arrayToAddFrom)
293 addAssumingCapacityIsReady (e);
296 template <
class OtherArrayType>
297 typename std::enable_if<! std::is_pointer<OtherArrayType>::value,
int>::type
298 addArray (
const OtherArrayType& arrayToAddFrom,
299 int startIndex,
int numElementsToAdd = -1)
301 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
309 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > (
int) arrayToAddFrom.size())
310 numElementsToAdd = (int) arrayToAddFrom.size() - startIndex;
312 addArray (arrayToAddFrom.data() + startIndex, numElementsToAdd);
314 return numElementsToAdd;
318 void insert (
int indexToInsertAt, ParameterType newElement,
int numberOfTimesToInsertIt)
320 checkSourceIsNotAMember (&newElement);
321 auto* space = createInsertSpace (indexToInsertAt, numberOfTimesToInsertIt);
323 for (
int i = 0; i < numberOfTimesToInsertIt; ++i)
324 new (space++) ElementType (newElement);
326 numUsed += numberOfTimesToInsertIt;
329 void insertArray (
int indexToInsertAt,
const ElementType* newElements,
int numberOfElements)
331 auto* space = createInsertSpace (indexToInsertAt, numberOfElements);
333 for (
int i = 0; i < numberOfElements; ++i)
334 new (space++) ElementType (*(newElements++));
336 numUsed += numberOfElements;
340 void removeElements (
int indexToRemoveAt,
int numElementsToRemove)
342 jassert (indexToRemoveAt >= 0);
343 jassert (numElementsToRemove >= 0);
344 jassert (indexToRemoveAt + numElementsToRemove <= numUsed);
346 if (numElementsToRemove > 0)
348 removeElementsInternal (indexToRemoveAt, numElementsToRemove);
349 numUsed -= numElementsToRemove;
354 void swap (
int index1,
int index2)
356 if (isPositiveAndBelow (index1, numUsed)
357 && isPositiveAndBelow (index2, numUsed))
359 std::swap (elements[index1],
365 void move (
int currentIndex,
int newIndex)
noexcept
367 if (isPositiveAndBelow (currentIndex, numUsed))
369 if (! isPositiveAndBelow (newIndex, numUsed))
370 newIndex = numUsed - 1;
372 moveInternal (currentIndex, newIndex);
378 template <
typename T>
379 #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
380 using IsTriviallyCopyable = std::is_scalar<T>;
382 using IsTriviallyCopyable = std::is_trivially_copyable<T>;
385 template <
typename T>
386 using TriviallyCopyableVoid =
typename std::enable_if<IsTriviallyCopyable<T>::value,
void>::type;
388 template <
typename T>
389 using NonTriviallyCopyableVoid =
typename std::enable_if<! IsTriviallyCopyable<T>::value,
void>::type;
392 template <
typename T = ElementType>
393 TriviallyCopyableVoid<T> addArrayInternal (
const ElementType* otherElements,
int numElements)
395 memcpy (elements + numUsed, otherElements, (
size_t) numElements *
sizeof (ElementType));
398 template <
typename Type,
typename T = ElementType>
399 TriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
401 auto* start = elements + numUsed;
403 while (--numElements >= 0)
404 new (start++) ElementType (*(otherElements++));
407 template <
typename Type,
typename T = ElementType>
408 NonTriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
410 auto* start = elements + numUsed;
412 while (--numElements >= 0)
413 new (start++) ElementType (*(otherElements++));
417 template <
typename T = ElementType>
418 TriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
420 elements.realloc ((
size_t) numElements);
423 template <
typename T = ElementType>
424 NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
426 HeapBlock<ElementType> newElements (numElements);
428 for (
int i = 0; i < numUsed; ++i)
430 new (newElements + i) ElementType (std::move (elements[i]));
431 elements[i].~ElementType();
434 elements = std::move (newElements);
438 ElementType* createInsertSpace (
int indexToInsertAt,
int numElements)
440 ensureAllocatedSize (numUsed + numElements);
442 if (! isPositiveAndBelow (indexToInsertAt, numUsed))
443 return elements + numUsed;
445 createInsertSpaceInternal (indexToInsertAt, numElements);
447 return elements + indexToInsertAt;
450 template <
typename T = ElementType>
451 TriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
453 auto* start = elements + indexToInsertAt;
454 auto numElementsToShift = numUsed - indexToInsertAt;
455 memmove (start + numElements, start, (
size_t) numElementsToShift *
sizeof (ElementType));
458 template <
typename T = ElementType>
459 NonTriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
461 auto* end = elements + numUsed;
462 auto* newEnd = end + numElements;
463 auto numElementsToShift = numUsed - indexToInsertAt;
465 for (
int i = 0; i < numElementsToShift; ++i)
467 new (--newEnd) ElementType (std::move (*(--end)));
473 template <
typename T = ElementType>
474 TriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
476 auto* start = elements + indexToRemoveAt;
477 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
478 memmove (start, start + numElementsToRemove, (
size_t) numElementsToShift *
sizeof (ElementType));
481 template <
typename T = ElementType>
482 NonTriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
484 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
485 auto* destination = elements + indexToRemoveAt;
486 auto* source = destination + numElementsToRemove;
488 for (
int i = 0; i < numElementsToShift; ++i)
489 moveAssignElement (destination++, std::move (*(source++)));
491 for (
int i = 0; i < numElementsToRemove; ++i)
492 (destination++)->~ElementType();
496 template <
typename T = ElementType>
497 TriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex)
noexcept
499 char tempCopy[
sizeof (ElementType)];
500 memcpy (tempCopy, elements + currentIndex,
sizeof (ElementType));
502 if (newIndex > currentIndex)
504 memmove (elements + currentIndex,
505 elements + currentIndex + 1,
506 sizeof (ElementType) * (
size_t) (newIndex - currentIndex));
510 memmove (elements + newIndex + 1,
512 sizeof (ElementType) * (
size_t) (currentIndex - newIndex));
515 memcpy (elements + newIndex, tempCopy,
sizeof (ElementType));
518 template <
typename T = ElementType>
519 NonTriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex)
noexcept
521 auto* e = elements + currentIndex;
522 ElementType tempCopy (std::move (*e));
523 auto delta = newIndex - currentIndex;
527 for (
int i = 0; i < delta; ++i)
529 moveAssignElement (e, std::move (*(e + 1)));
535 for (
int i = 0; i < -delta; ++i)
537 moveAssignElement (e, std::move (*(e - 1)));
542 moveAssignElement (e, std::move (tempCopy));
546 void addAssumingCapacityIsReady (
const ElementType& element) {
new (elements + numUsed++) ElementType (element); }
547 void addAssumingCapacityIsReady (ElementType&& element) {
new (elements + numUsed++) ElementType (std::move (element)); }
549 template <
typename... OtherElements>
550 void addAssumingCapacityIsReady (
const ElementType& firstNewElement, OtherElements... otherElements)
552 addAssumingCapacityIsReady (firstNewElement);
553 addAssumingCapacityIsReady (otherElements...);
556 template <
typename... OtherElements>
557 void addAssumingCapacityIsReady (ElementType&& firstNewElement, OtherElements... otherElements)
559 addAssumingCapacityIsReady (std::move (firstNewElement));
560 addAssumingCapacityIsReady (otherElements...);
564 template <
typename T = ElementType>
565 typename std::enable_if<std::is_move_assignable<T>::value,
void>::type
566 moveAssignElement (ElementType* destination, ElementType&& source)
568 *destination = std::move (source);
571 template <
typename T = ElementType>
572 typename std::enable_if<! std::is_move_assignable<T>::value,
void>::type
573 moveAssignElement (ElementType* destination, ElementType&& source)
575 destination->~ElementType();
576 new (destination) ElementType (std::move (source));
579 void checkSourceIsNotAMember (
const ElementType* element)
586 jassert (element < begin() || element >= end());
587 ignoreUnused (element);
591 HeapBlock<ElementType> elements;
592 int numAllocated = 0, numUsed = 0;
594 template <
class OtherElementType,
class OtherCriticalSection>
595 friend class ArrayBase;
597 JUCE_DECLARE_NON_COPYABLE (ArrayBase)