43 template <
class ElementType,
class TypeOfCriticalSectionToUse>
47 using ParameterType =
typename TypeHelpers::ParameterType<ElementType>::type;
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;
75 auto tmp (std::move (other));
87 template <
class OtherElementType,
88 class OtherCriticalSection,
89 typename = AllowConversion<OtherElementType, OtherCriticalSection>>
91 : elements (std::move (other.elements)),
92 numAllocated (other.numAllocated),
93 numUsed (other.numUsed)
95 other.numAllocated = 0;
104 template <
class OtherElementType,
105 class OtherCriticalSection,
106 typename = AllowConversion<OtherElementType, OtherCriticalSection>>
110 elements = std::move (other.elements);
111 numAllocated = other.numAllocated;
112 numUsed = other.numUsed;
114 other.numAllocated = 0;
121 template <
class OtherArrayType>
122 bool operator== (
const OtherArrayType& other)
const noexcept
124 if (size() != (
int) other.size())
129 for (
auto& o : other)
136 template <
class OtherArrayType>
137 bool operator!= (
const OtherArrayType& other)
const noexcept
139 return ! operator== (other);
143 inline ElementType& operator[] (
const int index) noexcept
145 jassert (elements !=
nullptr);
146 jassert (isPositiveAndBelow (index, numUsed));
147 return elements[index];
150 inline const ElementType& operator[] (
const int index)
const noexcept
152 jassert (elements !=
nullptr);
153 jassert (isPositiveAndBelow (index, numUsed));
154 return elements[index];
157 inline ElementType getValueWithDefault (
const int index)
const noexcept
159 return isPositiveAndBelow (index, numUsed) ? elements[index] : ElementType();
162 inline ElementType getFirst() const noexcept
164 return numUsed > 0 ? elements[0] : ElementType();
167 inline ElementType getLast() const noexcept
169 return numUsed > 0 ? elements[numUsed - 1] : ElementType();
173 inline ElementType* begin() noexcept
178 inline const ElementType* begin() const noexcept
183 inline ElementType* end() noexcept
185 return elements + numUsed;
188 inline const ElementType* end() const noexcept
190 return elements + numUsed;
193 inline ElementType* data() noexcept
198 inline const ElementType* data() const noexcept
203 inline int size() const noexcept
208 inline int capacity() const noexcept
214 void setAllocatedSize (
int numElements)
216 jassert (numElements >= numUsed);
218 if (numAllocated != numElements)
221 setAllocatedSizeInternal (numElements);
226 numAllocated = numElements;
229 void ensureAllocatedSize (
int minNumElements)
231 if (minNumElements > numAllocated)
232 setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
234 jassert (numAllocated <= 0 || elements !=
nullptr);
237 void shrinkToNoMoreThan (
int maxNumElements)
239 if (maxNumElements < numAllocated)
240 setAllocatedSize (maxNumElements);
245 for (
int i = 0; i < numUsed; ++i)
246 elements[i].~ElementType();
252 void swapWith (ArrayBase& other) noexcept
254 elements.swapWith (other.elements);
255 std::swap (numAllocated, other.numAllocated);
256 std::swap (numUsed, other.numUsed);
260 void add (
const ElementType& newElement)
262 checkSourceIsNotAMember (&newElement);
263 ensureAllocatedSize (numUsed + 1);
264 addAssumingCapacityIsReady (newElement);
267 void add (ElementType&& newElement)
269 checkSourceIsNotAMember (&newElement);
270 ensureAllocatedSize (numUsed + 1);
271 addAssumingCapacityIsReady (std::move (newElement));
274 template <
typename... OtherElements>
275 void add (
const ElementType& firstNewElement, OtherElements... otherElements)
277 checkSourceIsNotAMember (&firstNewElement);
278 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
279 addAssumingCapacityIsReady (firstNewElement, otherElements...);
282 template <
typename... OtherElements>
283 void add (ElementType&& firstNewElement, OtherElements... otherElements)
285 checkSourceIsNotAMember (&firstNewElement);
286 ensureAllocatedSize (numUsed + 1 + (
int)
sizeof... (otherElements));
287 addAssumingCapacityIsReady (std::move (firstNewElement), otherElements...);
291 template <
typename Type>
292 void addArray (
const Type* elementsToAdd,
int numElementsToAdd)
294 ensureAllocatedSize (numUsed + numElementsToAdd);
295 addArrayInternal (elementsToAdd, numElementsToAdd);
296 numUsed += numElementsToAdd;
299 template <
typename TypeToCreateFrom>
300 void addArray (
const std::initializer_list<TypeToCreateFrom>& items)
302 ensureAllocatedSize (numUsed + (
int) items.size());
304 for (
auto& item : items)
305 new (elements + numUsed++) ElementType (item);
308 template <
class OtherArrayType>
309 void addArray (
const OtherArrayType& arrayToAddFrom)
311 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
312 ensureAllocatedSize (numUsed + (
int) arrayToAddFrom.size());
314 for (
auto& e : arrayToAddFrom)
315 addAssumingCapacityIsReady (e);
318 template <
class OtherArrayType>
319 typename std::enable_if<! std::is_pointer<OtherArrayType>::value,
int>::type
320 addArray (
const OtherArrayType& arrayToAddFrom,
321 int startIndex,
int numElementsToAdd = -1)
323 jassert ((
const void*)
this != (
const void*) &arrayToAddFrom);
331 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > (
int) arrayToAddFrom.size())
332 numElementsToAdd = (int) arrayToAddFrom.size() - startIndex;
334 addArray (arrayToAddFrom.data() + startIndex, numElementsToAdd);
336 return numElementsToAdd;
340 void insert (
int indexToInsertAt, ParameterType newElement,
int numberOfTimesToInsertIt)
342 checkSourceIsNotAMember (&newElement);
343 auto* space = createInsertSpace (indexToInsertAt, numberOfTimesToInsertIt);
345 for (
int i = 0; i < numberOfTimesToInsertIt; ++i)
346 new (space++) ElementType (newElement);
348 numUsed += numberOfTimesToInsertIt;
351 void insertArray (
int indexToInsertAt,
const ElementType* newElements,
int numberOfElements)
353 auto* space = createInsertSpace (indexToInsertAt, numberOfElements);
355 for (
int i = 0; i < numberOfElements; ++i)
356 new (space++) ElementType (*(newElements++));
358 numUsed += numberOfElements;
362 void removeElements (
int indexToRemoveAt,
int numElementsToRemove)
364 jassert (indexToRemoveAt >= 0);
365 jassert (numElementsToRemove >= 0);
366 jassert (indexToRemoveAt + numElementsToRemove <= numUsed);
368 if (numElementsToRemove > 0)
370 removeElementsInternal (indexToRemoveAt, numElementsToRemove);
371 numUsed -= numElementsToRemove;
376 void swap (
int index1,
int index2)
378 if (isPositiveAndBelow (index1, numUsed)
379 && isPositiveAndBelow (index2, numUsed))
381 std::swap (elements[index1],
387 void move (
int currentIndex,
int newIndex) noexcept
389 if (isPositiveAndBelow (currentIndex, numUsed))
391 if (! isPositiveAndBelow (newIndex, numUsed))
392 newIndex = numUsed - 1;
394 moveInternal (currentIndex, newIndex);
400 template <
typename T>
401 #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
402 using IsTriviallyCopyable = std::is_scalar<T>;
404 using IsTriviallyCopyable = std::is_trivially_copyable<T>;
407 template <
typename T>
408 using TriviallyCopyableVoid =
typename std::enable_if<IsTriviallyCopyable<T>::value,
void>::type;
410 template <
typename T>
411 using NonTriviallyCopyableVoid =
typename std::enable_if<! IsTriviallyCopyable<T>::value,
void>::type;
414 template <
typename T = ElementType>
415 TriviallyCopyableVoid<T> addArrayInternal (
const ElementType* otherElements,
int numElements)
417 memcpy (elements + numUsed, otherElements, (
size_t) numElements *
sizeof (ElementType));
420 template <
typename Type,
typename T = ElementType>
421 TriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
423 auto* start = elements + numUsed;
425 while (--numElements >= 0)
426 new (start++) ElementType (*(otherElements++));
429 template <
typename Type,
typename T = ElementType>
430 NonTriviallyCopyableVoid<T> addArrayInternal (
const Type* otherElements,
int numElements)
432 auto* start = elements + numUsed;
434 while (--numElements >= 0)
435 new (start++) ElementType (*(otherElements++));
439 template <
typename T = ElementType>
440 TriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
442 elements.realloc ((
size_t) numElements);
445 template <
typename T = ElementType>
446 NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (
int numElements)
448 HeapBlock<ElementType> newElements (numElements);
450 for (
int i = 0; i < numUsed; ++i)
452 new (newElements + i) ElementType (std::move (elements[i]));
453 elements[i].~ElementType();
456 elements = std::move (newElements);
460 ElementType* createInsertSpace (
int indexToInsertAt,
int numElements)
462 ensureAllocatedSize (numUsed + numElements);
464 if (! isPositiveAndBelow (indexToInsertAt, numUsed))
465 return elements + numUsed;
467 createInsertSpaceInternal (indexToInsertAt, numElements);
469 return elements + indexToInsertAt;
472 template <
typename T = ElementType>
473 TriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
475 auto* start = elements + indexToInsertAt;
476 auto numElementsToShift = numUsed - indexToInsertAt;
477 memmove (start + numElements, start, (
size_t) numElementsToShift *
sizeof (ElementType));
480 template <
typename T = ElementType>
481 NonTriviallyCopyableVoid<T> createInsertSpaceInternal (
int indexToInsertAt,
int numElements)
483 auto* end = elements + numUsed;
484 auto* newEnd = end + numElements;
485 auto numElementsToShift = numUsed - indexToInsertAt;
487 for (
int i = 0; i < numElementsToShift; ++i)
489 new (--newEnd) ElementType (std::move (*(--end)));
495 template <
typename T = ElementType>
496 TriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
498 auto* start = elements + indexToRemoveAt;
499 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
500 memmove (start, start + numElementsToRemove, (
size_t) numElementsToShift *
sizeof (ElementType));
503 template <
typename T = ElementType>
504 NonTriviallyCopyableVoid<T> removeElementsInternal (
int indexToRemoveAt,
int numElementsToRemove)
506 auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
507 auto* destination = elements + indexToRemoveAt;
508 auto* source = destination + numElementsToRemove;
510 for (
int i = 0; i < numElementsToShift; ++i)
511 moveAssignElement (destination++, std::move (*(source++)));
513 for (
int i = 0; i < numElementsToRemove; ++i)
514 (destination++)->~ElementType();
518 template <
typename T = ElementType>
519 TriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex) noexcept
521 char tempCopy[
sizeof (ElementType)];
522 memcpy (tempCopy, elements + currentIndex,
sizeof (ElementType));
524 if (newIndex > currentIndex)
526 memmove (elements + currentIndex,
527 elements + currentIndex + 1,
528 (
size_t) (newIndex - currentIndex) *
sizeof (ElementType));
532 memmove (elements + newIndex + 1,
534 (
size_t) (currentIndex - newIndex) *
sizeof (ElementType));
537 memcpy (elements + newIndex, tempCopy,
sizeof (ElementType));
540 template <
typename T = ElementType>
541 NonTriviallyCopyableVoid<T> moveInternal (
int currentIndex,
int newIndex) noexcept
543 auto* e = elements + currentIndex;
544 ElementType tempCopy (std::move (*e));
545 auto delta = newIndex - currentIndex;
549 for (
int i = 0; i < delta; ++i)
551 moveAssignElement (e, std::move (*(e + 1)));
557 for (
int i = 0; i < -delta; ++i)
559 moveAssignElement (e, std::move (*(e - 1)));
564 moveAssignElement (e, std::move (tempCopy));
568 void addAssumingCapacityIsReady (
const ElementType& element) {
new (elements + numUsed++) ElementType (element); }
569 void addAssumingCapacityIsReady (ElementType&& element) {
new (elements + numUsed++) ElementType (std::move (element)); }
571 template <
typename... OtherElements>
572 void addAssumingCapacityIsReady (
const ElementType& firstNewElement, OtherElements... otherElements)
574 addAssumingCapacityIsReady (firstNewElement);
575 addAssumingCapacityIsReady (otherElements...);
578 template <
typename... OtherElements>
579 void addAssumingCapacityIsReady (ElementType&& firstNewElement, OtherElements... otherElements)
581 addAssumingCapacityIsReady (std::move (firstNewElement));
582 addAssumingCapacityIsReady (otherElements...);
586 template <
typename T = ElementType>
587 typename std::enable_if<std::is_move_assignable<T>::value,
void>::type
588 moveAssignElement (ElementType* destination, ElementType&& source)
590 *destination = std::move (source);
593 template <
typename T = ElementType>
594 typename std::enable_if<! std::is_move_assignable<T>::value,
void>::type
595 moveAssignElement (ElementType* destination, ElementType&& source)
597 destination->~ElementType();
598 new (destination) ElementType (std::move (source));
601 void checkSourceIsNotAMember (
const ElementType* element)
608 jassert (element < begin() || element >= end());
609 ignoreUnused (element);
613 HeapBlock<ElementType> elements;
614 int numAllocated = 0, numUsed = 0;
616 template <
class OtherElementType,
class OtherCriticalSection>
617 friend class ArrayBase;
619 JUCE_DECLARE_NON_COPYABLE (ArrayBase)
A basic object container.
ArrayBase(ArrayBase< OtherElementType, OtherCriticalSection > &&other) noexcept
Converting move constructor.