JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_OwnedArray.h
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26//==============================================================================
47template <class ObjectClass,
48 class TypeOfCriticalSectionToUse = DummyCriticalSection>
50{
51public:
52 //==============================================================================
54 OwnedArray() = default;
55
62 {
63 deleteAllObjects();
64 }
65
68 : values (std::move (other.values))
69 {
70 }
71
74 {
75 addArray (items);
76 }
77
80 {
81 const ScopedLockType lock (getLock());
82 deleteAllObjects();
83 values = std::move (other.values);
84 return *this;
85 }
86
88 template <class OtherObjectClass, class OtherCriticalSection>
90 : values (std::move (other.values))
91 {
92 }
93
95 template <class OtherObjectClass, class OtherCriticalSection>
97 {
98 const ScopedLockType lock (getLock());
99 deleteAllObjects();
100 values = std::move (other.values);
101 return *this;
102 }
103
104 //==============================================================================
106 void clear (bool deleteObjects = true)
107 {
108 const ScopedLockType lock (getLock());
110 values.setAllocatedSize (0);
111 }
112
113 //==============================================================================
116 {
117 const ScopedLockType lock (getLock());
118
119 if (deleteObjects)
120 deleteAllObjects();
121 else
122 values.clear();
123 }
124
125 //==============================================================================
129 inline int size() const noexcept
130 {
131 return values.size();
132 }
133
135 inline bool isEmpty() const noexcept
136 {
137 return size() == 0;
138 }
139
148 inline ObjectClass* operator[] (int index) const noexcept
149 {
150 const ScopedLockType lock (getLock());
151 return values.getValueWithDefault (index);
152 }
153
159 inline ObjectClass* getUnchecked (int index) const noexcept
160 {
161 const ScopedLockType lock (getLock());
162 return values[index];
163 }
164
170 inline ObjectClass* getFirst() const noexcept
171 {
172 const ScopedLockType lock (getLock());
173 return values.getFirst();
174 }
175
181 inline ObjectClass* getLast() const noexcept
182 {
183 const ScopedLockType lock (getLock());
184 return values.getLast();
185 }
186
191 inline ObjectClass** getRawDataPointer() noexcept
192 {
193 return values.begin();
194 }
195
196 //==============================================================================
200 inline ObjectClass** begin() noexcept
201 {
202 return values.begin();
203 }
204
208 inline ObjectClass* const* begin() const noexcept
209 {
210 return values.begin();
211 }
212
216 inline ObjectClass** end() noexcept
217 {
218 return values.end();
219 }
220
224 inline ObjectClass* const* end() const noexcept
225 {
226 return values.end();
227 }
228
232 inline ObjectClass** data() noexcept
233 {
234 return begin();
235 }
236
240 inline ObjectClass* const* data() const noexcept
241 {
242 return begin();
243 }
244
245 //==============================================================================
251 int indexOf (const ObjectClass* objectToLookFor) const noexcept
252 {
253 const ScopedLockType lock (getLock());
254 auto* e = values.begin();
255
256 for (; e != values.end(); ++e)
257 if (objectToLookFor == *e)
258 return static_cast<int> (e - values.begin());
259
260 return -1;
261 }
262
268 bool contains (const ObjectClass* objectToLookFor) const noexcept
269 {
270 const ScopedLockType lock (getLock());
271 auto* e = values.begin();
272
273 for (; e != values.end(); ++e)
274 if (objectToLookFor == *e)
275 return true;
276
277 return false;
278 }
279
280 //==============================================================================
293 ObjectClass* add (ObjectClass* newObject)
294 {
295 const ScopedLockType lock (getLock());
296 values.add (newObject);
297 return newObject;
298 }
299
313 {
314 return add (newObject.release());
315 }
316
335 ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
336 {
337 const ScopedLockType lock (getLock());
338 values.insert (indexToInsertAt, newObject, 1);
339 return newObject;
340 }
341
361 {
362 return insert (indexToInsertAt, newObject.release());
363 }
364
378 ObjectClass* const* newObjects,
380 {
381 if (numberOfElements > 0)
382 {
383 const ScopedLockType lock (getLock());
384 values.insertArray (indexToInsertAt, newObjects, numberOfElements);
385 }
386 }
387
401 ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
402 {
403 if (indexToChange >= 0)
404 {
406
407 {
408 const ScopedLockType lock (getLock());
409
410 if (indexToChange < values.size())
411 {
413 {
414 toDelete.reset (values[indexToChange]);
415
416 if (toDelete.get() == newObject)
417 toDelete.release();
418 }
419
420 values[indexToChange] = newObject;
421 }
422 else
423 {
424 values.add (newObject);
425 }
426 }
427 }
428 else
429 {
430 jassertfalse; // you're trying to set an object at a negative index, which doesn't have
431 // any effect - but since the object is not being added, it may be leaking..
432 }
433
434 return newObject;
435 }
436
451 {
452 return set (indexToChange, newObject.release(), deleteOldElement);
453 }
454
464 template <class OtherArrayType>
466 int startIndex = 0,
467 int numElementsToAdd = -1)
468 {
469 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
470 const ScopedLockType lock2 (getLock());
471 values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
472 }
473
475 template <typename OtherArrayType>
477 {
478 const ScopedLockType lock (getLock());
479 values.addArray (items);
480 }
481
496 template <class OtherArrayType>
498 int startIndex = 0,
499 int numElementsToAdd = -1)
500 {
501 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
502 const ScopedLockType lock2 (getLock());
503
504 if (startIndex < 0)
505 {
507 startIndex = 0;
508 }
509
511 numElementsToAdd = arrayToAddFrom.size() - startIndex;
512
514 values.ensureAllocatedSize (values.size() + numElementsToAdd);
515
516 while (--numElementsToAdd >= 0)
517 values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
518 }
519
532 template <class ElementComparator>
533 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept;
534
547 template <typename ElementComparator>
548 int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;
549
550 //==============================================================================
561 void remove (int indexToRemove, bool deleteObject = true)
562 {
564
565 {
566 const ScopedLockType lock (getLock());
567
568 if (isPositiveAndBelow (indexToRemove, values.size()))
569 {
570 auto** e = values.begin() + indexToRemove;
571
572 if (deleteObject)
573 toDelete.reset (*e);
574
575 values.removeElements (indexToRemove, 1);
576 }
577 }
578
579 if ((values.size() << 1) < values.capacity())
581 }
582
593 {
594 ObjectClass* removedItem = nullptr;
595 const ScopedLockType lock (getLock());
596
597 if (isPositiveAndBelow (indexToRemove, values.size()))
598 {
599 removedItem = values[indexToRemove];
600
601 values.removeElements (indexToRemove, 1);
602
603 if ((values.size() << 1) < values.capacity())
605 }
606
607 return removedItem;
608 }
609
618 void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
619 {
620 const ScopedLockType lock (getLock());
621
622 for (int i = 0; i < values.size(); ++i)
623 {
624 if (objectToRemove == values[i])
625 {
626 remove (i, deleteObject);
627 break;
628 }
629 }
630 }
631
645 void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
646 {
647 const ScopedLockType lock (getLock());
648 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
649 startIndex = jlimit (0, values.size(), startIndex);
650 numberToRemove = endIndex - startIndex;
651
652 if (numberToRemove > 0)
653 {
655
656 if (deleteObjects)
657 objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
658
659 values.removeElements (startIndex, numberToRemove);
660
661 for (auto& o : objectsToDelete)
663
664 if ((values.size() << 1) < values.capacity())
666 }
667 }
668
676 bool deleteObjects = true)
677 {
678 const ScopedLockType lock (getLock());
679
680 if (howManyToRemove >= values.size())
682 else
684 }
685
691 void swap (int index1, int index2) noexcept
692 {
693 const ScopedLockType lock (getLock());
694 values.swap (index1, index2);
695 }
696
710 void move (int currentIndex, int newIndex) noexcept
711 {
712 if (currentIndex != newIndex)
713 {
714 const ScopedLockType lock (getLock());
715 values.move (currentIndex, newIndex);
716 }
717 }
718
724 template <class OtherArrayType>
726 {
727 const ScopedLockType lock1 (getLock());
728 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
729 values.swapWith (otherArray.values);
730 }
731
732 //==============================================================================
740 {
741 const ScopedLockType lock (getLock());
742 values.shrinkToNoMoreThan (values.size());
743 }
744
752 {
753 const ScopedLockType lock (getLock());
754 values.ensureAllocatedSize (minNumElements);
755 }
756
757 //==============================================================================
783 template <class ElementComparator>
784 void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;
785
786 //==============================================================================
791 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
792
794 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
795
796 //==============================================================================
797 #ifndef DOXYGEN
798 [[deprecated ("This method has been replaced by a more flexible templated version and renamed "
799 "to swapWith to be more consistent with the names used in other classes.")]]
800 void swapWithArray (OwnedArray& other) noexcept { swapWith (other); }
801 #endif
802
803private:
804 //==============================================================================
806
807 void deleteAllObjects()
808 {
809 auto i = values.size();
810
811 while (--i >= 0)
812 {
813 auto* e = values[i];
814 values.removeElements (i, 1);
816 }
817 }
818
819 template <class OtherObjectClass, class OtherCriticalSection>
820 friend class OwnedArray;
821
823};
824
825//==============================================================================
826template <class ObjectClass, class TypeOfCriticalSectionToUse>
827template <class ElementComparator>
829 [[maybe_unused]] ElementComparator& comparator,
830 ObjectClass* newObject) noexcept
831{
832 const ScopedLockType lock (getLock());
833 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
834 insert (index, newObject);
835 return index;
836}
837
838template <class ObjectClass, class TypeOfCriticalSectionToUse>
839template <typename ElementComparator>
841 [[maybe_unused]] ElementComparator& comparator,
842 const ObjectClass* objectToLookFor) const noexcept
843{
844 const ScopedLockType lock (getLock());
845 int s = 0, e = values.size();
846
847 while (s < e)
848 {
849 if (comparator.compareElements (objectToLookFor, values[s]) == 0)
850 return s;
851
852 auto halfway = (s + e) / 2;
853
854 if (halfway == s)
855 break;
856
857 if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
858 s = halfway;
859 else
860 e = halfway;
861 }
862
863 return -1;
864}
865
866template <class ObjectClass, class TypeOfCriticalSectionToUse>
867template <typename ElementComparator>
869 [[maybe_unused]] ElementComparator& comparator,
870 bool retainOrderOfEquivalentItems) noexcept
871{
872 const ScopedLockType lock (getLock());
873
874 if (size() > 1)
875 sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
876}
877
878} // namespace juce
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition juce_Array.h:583
An array designed for holding objects.
ObjectClass *const * data() const noexcept
Returns a pointer to the first element in the array.
int size() const noexcept
Returns the number of items currently in the array.
ObjectClass * getUnchecked(int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
ObjectClass * set(int indexToChange, ObjectClass *newObject, bool deleteOldElement=true)
Replaces an object in the array with a different one.
ObjectClass * removeAndReturn(int indexToRemove)
Removes and returns an object from the array without deleting it.
ObjectClass * add(std::unique_ptr< ObjectClass > newObject)
Appends a new object to the end of the array.
ObjectClass * set(int indexToChange, std::unique_ptr< ObjectClass > newObject, bool deleteOldElement=true)
Replaces an object in the array with a different one.
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Adds copies of the elements in another array to the end of this array.
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Adds elements from another array to the end of this array.
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
void remove(int indexToRemove, bool deleteObject=true)
Removes an object from the array.
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
void ensureStorageAllocated(int minNumElements) noexcept
Increases the array's internal storage to hold a minimum number of elements.
ObjectClass * getFirst() const noexcept
Returns a pointer to the first object in the array.
void minimiseStorageOverheads() noexcept
Reduces the amount of storage being used by the array.
void clear(bool deleteObjects=true)
Clears the array, optionally deleting the objects inside it first.
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
Removes the last n objects from the array.
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object which might be in the array.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
ObjectClass ** begin() noexcept
Returns a pointer to the first element in the array.
OwnedArray(OwnedArray< OtherObjectClass, OtherCriticalSection > &&other) noexcept
Converting move constructor.
~OwnedArray()
Deletes the array and also deletes any objects inside it.
void swap(int index1, int index2) noexcept
Swaps a pair of objects in the array.
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object in the array, assuming that the array is sorted.
ObjectClass * insert(int indexToInsertAt, std::unique_ptr< ObjectClass > newObject)
Inserts a new object into the array at the given index.
void clearQuick(bool deleteObjects)
Clears the array, optionally deleting the objects inside it first.
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
Removes a specified object from the array.
ObjectClass *const * begin() const noexcept
Returns a pointer to the first element in the array.
ObjectClass *const * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
ObjectClass ** end() noexcept
Returns a pointer to the element which follows the last element in the array.
OwnedArray()=default
Creates an empty array.
OwnedArray & operator=(OwnedArray &&other) noexcept
Move assignment operator.
OwnedArray(OwnedArray &&other) noexcept
Move constructor.
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
Inserts an array of values into this array at a given position.
void move(int currentIndex, int newIndex) noexcept
Moves one of the objects to a different position.
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts a new object into the array assuming that the array is sorted.
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
void addArray(const std::initializer_list< OtherArrayType > &items)
Adds elements from another array to the end of this array.
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Sorts the elements in the array.
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Inserts a new object into the array at the given index.
ObjectClass * operator[](int index) const noexcept
Returns a pointer to the object at this index in the array.
ObjectClass ** getRawDataPointer() noexcept
Returns a pointer to the actual array data.
ObjectClass ** data() noexcept
Returns a pointer to the first element in the array.
OwnedArray(const std::initializer_list< ObjectClass * > &items)
Creates an array from a list of objects.
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
Removes a range of objects from the array.
ObjectClass * getLast() const noexcept
Returns a pointer to the last object in the array.
bool contains(const ObjectClass *objectToLookFor) const noexcept
Returns true if the array contains a specified object.
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
#define jassertfalse
This will always cause an assertion failure.
JUCE Namespace.
Type * createCopyIfNotNull(const Type *objectToCopy)
If a pointer is non-null, this returns a new copy of the object that it points to,...
Definition juce_Memory.h:60
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Constrains a value to keep it within a given range.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
Used by container classes as an indirect way to delete an object of a particular type.