43 using ParameterType =
typename TypeHelpers::ParameterType<ElementType>::type;
45 template <
class OtherElementType,
class OtherCriticalSection>
46 using AllowConversion =
typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>,
47 std::tuple<OtherElementType, OtherCriticalSection>>::value>::type;
59 : elements (std::move (
other.elements)),
60 numAllocated (
other.numAllocated),
61 numUsed (
other.numUsed)
63 other.numAllocated = 0;
87 : elements (std::move (
other.elements)),
88 numAllocated (
other.numAllocated),
89 numUsed (
other.numUsed)
91 other.numAllocated = 0;
106 elements = std::move (
other.elements);
107 numAllocated =
other.numAllocated;
108 numUsed =
other.numUsed;
110 other.numAllocated = 0;
117 template <
class OtherArrayType>
132 template <
class OtherArrayType>
133 bool operator!= (
const OtherArrayType& other)
const noexcept
135 return ! operator== (other);
139 inline ElementType& operator[] (
const int index)
noexcept
141 jassert (elements !=
nullptr);
142 jassert (isPositiveAndBelow (index, numUsed));
143 return elements[index];
146 inline const ElementType& operator[] (
const int index)
const noexcept
148 jassert (elements !=
nullptr);
149 jassert (isPositiveAndBelow (index, numUsed));
150 return elements[index];
153 inline ElementType getValueWithDefault (
const int index)
const noexcept
155 return isPositiveAndBelow (index, numUsed) ? elements[index] : ElementType();
158 inline ElementType getFirst() const noexcept
160 return numUsed > 0 ? elements[0] : ElementType();
163 inline ElementType getLast() const noexcept
165 return numUsed > 0 ? elements[numUsed - 1] : ElementType();
169 inline ElementType* begin() noexcept
174 inline const ElementType* begin() const noexcept
179 inline ElementType* end() noexcept
181 return elements + numUsed;
184 inline const ElementType* end() const noexcept
186 return elements + numUsed;
189 inline ElementType* data() noexcept
194 inline const ElementType* data() const noexcept
199 inline int size() const noexcept
204 inline int capacity() const noexcept
210 void setAllocatedSize (
int numElements)
212 jassert (numElements >= numUsed);
214 if (numAllocated != numElements)
217 setAllocatedSizeInternal (numElements);
222 numAllocated = numElements;
225 void ensureAllocatedSize (
int minNumElements)
227 if (minNumElements > numAllocated)
228 setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
230 jassert (numAllocated <= 0 || elements !=
nullptr);
233 void shrinkToNoMoreThan (
int maxNumElements)
235 if (maxNumElements < numAllocated)
236 setAllocatedSize (maxNumElements);
241 for (
int i = 0; i < numUsed; ++i)
242 elements[i].~ElementType();
248 void swapWith (ArrayBase& other)
noexcept
251 std::swap (numAllocated, other.numAllocated);
252 std::swap (numUsed, other.numUsed);
256 void add (
const ElementType& newElement)
258 checkSourceIsNotAMember (&newElement);
259 ensureAllocatedSize (numUsed + 1);
260 addAssumingCapacityIsReady (newElement);
263 void add (ElementType&& newElement)
265 checkSourceIsNotAMember (&newElement);
266 ensureAllocatedSize (numUsed + 1);
267 addAssumingCapacityIsReady (std::move (newElement));
270 template <
typename... OtherElements>
271 void add (
const ElementType& firstNewElement, OtherElements... otherElements)
273 checkSourceIsNotAMember (&firstNewElement);
274 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
275 addAssumingCapacityIsReady (firstNewElement, otherElements...);
278 template <
typename... OtherElements>
279 void add (ElementType&& firstNewElement, OtherElements... otherElements)
281 checkSourceIsNotAMember (&firstNewElement);
282 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
283 addAssumingCapacityIsReady (std::move (firstNewElement), otherElements...);
287 template <
typename Type>
288 void addArray (
const Type* elementsToAdd,
int numElementsToAdd)
290 ensureAllocatedSize (numUsed + numElementsToAdd);
291 addArrayInternal (elementsToAdd, numElementsToAdd);
292 numUsed += numElementsToAdd;
295 template <
typename TypeToCreateFrom>
296 void addArray (
const std::initializer_list<TypeToCreateFrom>& items)
298 ensureAllocatedSize (numUsed + (
int) items.size());
300 for (
auto& item : items)
301 new (elements + numUsed++) ElementType (item);
304 template <
class OtherArrayType>
305 void addArray (
const OtherArrayType& arrayToAddFrom)
307 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
308 ensureAllocatedSize (numUsed + (
int) arrayToAddFrom.size());
310 for (
auto& e : arrayToAddFrom)
311 addAssumingCapacityIsReady (e);
314 template <
class OtherArrayType>
315 typename std::enable_if<! std::is_pointer<OtherArrayType>::value,
int>::type
316 addArray (
const OtherArrayType& arrayToAddFrom,
317 int startIndex,
int numElementsToAdd = -1)
319 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
327 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > (
int) arrayToAddFrom.size())
328 numElementsToAdd = (int) arrayToAddFrom.size() - startIndex;
330 addArray (arrayToAddFrom.data() + startIndex, numElementsToAdd);
332 return numElementsToAdd;
336 void insert (
int indexToInsertAt, ParameterType newElement,
int numberOfTimesToInsertIt)
338 checkSourceIsNotAMember (&newElement);
339 auto* space = createInsertSpace (indexToInsertAt, numberOfTimesToInsertIt);
341 for (
int i = 0; i < numberOfTimesToInsertIt; ++i)
342 new (space++) ElementType (newElement);
344 numUsed += numberOfTimesToInsertIt;
347 void insertArray (
int indexToInsertAt,
const ElementType* newElements,
int numberOfElements)
349 auto* space = createInsertSpace (indexToInsertAt, numberOfElements);
351 for (
int i = 0; i < numberOfElements; ++i)
352 new (space++) ElementType (*(newElements++));
354 numUsed += numberOfElements;
358 void removeElements (
int indexToRemoveAt,
int numElementsToRemove)
360 jassert (indexToRemoveAt >= 0);
361 jassert (numElementsToRemove >= 0);
362 jassert (indexToRemoveAt + numElementsToRemove <= numUsed);
364 if (numElementsToRemove > 0)
366 removeElementsInternal (indexToRemoveAt, numElementsToRemove);
367 numUsed -= numElementsToRemove;
372 void swap (
int index1,
int index2)
374 if (isPositiveAndBelow (index1, numUsed)
375 && isPositiveAndBelow (index2, numUsed))
377 std::swap (elements[index1],
383 void move (
int currentIndex,
int newIndex)
noexcept
385 if (isPositiveAndBelow (currentIndex, numUsed))
387 if (! isPositiveAndBelow (newIndex, numUsed))
388 newIndex = numUsed - 1;
390 moveInternal (currentIndex, newIndex);
396 template <
typename T>
397 #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
398 using IsTriviallyCopyable = std::is_scalar<T>;
400 using IsTriviallyCopyable = std::is_trivially_copyable<T>;
403 template <
typename T>
404 using TriviallyCopyableVoid =
typename std::enable_if<IsTriviallyCopyable<T>::value,
void>::type;
406 template <
typename T>
407 using NonTriviallyCopyableVoid =
typename std::enable_if<! IsTriviallyCopyable<T>::value,
void>::type;
410 template <
typename T = ElementType>
411 TriviallyCopyableVoid<T> addArrayInternal (
const ElementType* otherElements,
int numElements)
413 memcpy (elements + numUsed, otherElements, (
size_t) numElements *
sizeof (ElementType));
416 template <
typename Type,
typename T = ElementType>
417 TriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
419 auto* start = elements + numUsed;
421 while (--numElements >= 0)
422 new (start++) ElementType (*(otherElements++));
425 template <
typename Type,
typename T = ElementType>
426 NonTriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
428 auto* start = elements + numUsed;
430 while (--numElements >= 0)
431 new (start++) ElementType (*(otherElements++));
435 template <
typename T = ElementType>
436 TriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
438 elements.realloc ((
size_t) numElements);
441 template <
typename T = ElementType>
442 NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
444 HeapBlock<ElementType> newElements (numElements);
446 for (
int i = 0; i < numUsed; ++i)
448 new (newElements + i) ElementType (std::move (elements[i]));
449 elements[i].~ElementType();
452 elements = std::move (newElements);
456 ElementType* createInsertSpace (
int indexToInsertAt,
int numElements)
458 ensureAllocatedSize (numUsed + numElements);
460 if (! isPositiveAndBelow (indexToInsertAt, numUsed))
461 return elements + numUsed;
463 createInsertSpaceInternal (indexToInsertAt, numElements);
465 return elements + indexToInsertAt;
468 template <
typename T = ElementType>
469 TriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
471 auto* start = elements + indexToInsertAt;
472 auto numElementsToShift = numUsed - indexToInsertAt;
473 memmove (start + numElements, start, (
size_t) numElementsToShift *
sizeof (ElementType));
476 template <
typename T = ElementType>
477 NonTriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
479 auto* end = elements + numUsed;
480 auto* newEnd = end + numElements;
481 auto numElementsToShift = numUsed - indexToInsertAt;
483 for (
int i = 0; i < numElementsToShift; ++i)
485 new (--newEnd) ElementType (std::move (*(--end)));
491 template <
typename T = ElementType>
492 TriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
494 auto* start = elements + indexToRemoveAt;
495 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
496 memmove (start, start + numElementsToRemove, (
size_t) numElementsToShift *
sizeof (ElementType));
499 template <
typename T = ElementType>
500 NonTriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
502 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
503 auto* destination = elements + indexToRemoveAt;
504 auto* source = destination + numElementsToRemove;
506 for (
int i = 0; i < numElementsToShift; ++i)
507 moveAssignElement (destination++, std::move (*(source++)));
509 for (
int i = 0; i < numElementsToRemove; ++i)
510 (destination++)->~ElementType();
514 template <
typename T = ElementType>
515 TriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex)
noexcept
517 char tempCopy[
sizeof (ElementType)];
518 memcpy (tempCopy, elements + currentIndex,
sizeof (ElementType));
520 if (newIndex > currentIndex)
522 memmove (elements + currentIndex,
523 elements + currentIndex + 1,
524 (
size_t) (newIndex - currentIndex) *
sizeof (ElementType));
528 memmove (elements + newIndex + 1,
530 (
size_t) (currentIndex - newIndex) *
sizeof (ElementType));
533 memcpy (elements + newIndex, tempCopy,
sizeof (ElementType));
536 template <
typename T = ElementType>
537 NonTriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex)
noexcept
539 auto* e = elements + currentIndex;
540 ElementType tempCopy (std::move (*e));
541 auto delta = newIndex - currentIndex;
545 for (
int i = 0; i < delta; ++i)
547 moveAssignElement (e, std::move (*(e + 1)));
553 for (
int i = 0; i < -delta; ++i)
555 moveAssignElement (e, std::move (*(e - 1)));
560 moveAssignElement (e, std::move (tempCopy));
564 void addAssumingCapacityIsReady (
const ElementType& element) {
new (elements + numUsed++) ElementType (element); }
565 void addAssumingCapacityIsReady (ElementType&& element) {
new (elements + numUsed++) ElementType (std::move (element)); }
567 template <
typename... OtherElements>
568 void addAssumingCapacityIsReady (
const ElementType& firstNewElement, OtherElements... otherElements)
570 addAssumingCapacityIsReady (firstNewElement);
571 addAssumingCapacityIsReady (otherElements...);
574 template <
typename... OtherElements>
575 void addAssumingCapacityIsReady (ElementType&& firstNewElement, OtherElements... otherElements)
577 addAssumingCapacityIsReady (std::move (firstNewElement));
578 addAssumingCapacityIsReady (otherElements...);
582 template <
typename T = ElementType>
583 typename std::enable_if<std::is_move_assignable<T>::value,
void>::type
584 moveAssignElement (ElementType* destination, ElementType&& source)
586 *destination = std::move (source);
589 template <
typename T = ElementType>
590 typename std::enable_if<! std::is_move_assignable<T>::value,
void>::type
591 moveAssignElement (ElementType* destination, ElementType&& source)
593 destination->~ElementType();
594 new (destination) ElementType (std::move (source));
597 void checkSourceIsNotAMember (
const ElementType* element)
604 jassert (element < begin() || element >= end());
605 ignoreUnused (element);
609 HeapBlock<ElementType> elements;
610 int numAllocated = 0, numUsed = 0;
612 template <
class OtherElementType,
class OtherCriticalSection>
613 friend class ArrayBase;
615 JUCE_DECLARE_NON_COPYABLE (ArrayBase)