OpenShot Audio Library | OpenShotAudio 0.4.0
 
Loading...
Searching...
No Matches
juce_OwnedArray.h
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>
49class OwnedArray
50{
51public:
52 //==============================================================================
54 OwnedArray() = default;
55
62 {
63 deleteAllObjects();
64 }
65
67 OwnedArray (OwnedArray&& other) noexcept
68 : values (std::move (other.values))
69 {
70 }
71
73 OwnedArray (const std::initializer_list<ObjectClass*>& items)
74 {
75 addArray (items);
76 }
77
79 OwnedArray& operator= (OwnedArray&& other) noexcept
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>
89 OwnedArray (OwnedArray<OtherObjectClass, OtherCriticalSection>&& other) noexcept
90 : values (std::move (other.values))
91 {
92 }
93
95 template <class OtherObjectClass, class OtherCriticalSection>
96 OwnedArray& operator= (OwnedArray<OtherObjectClass, OtherCriticalSection>&& other) noexcept
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());
109 clearQuick (deleteObjects);
110 values.setAllocatedSize (0);
111 }
112
113 //==============================================================================
115 void clearQuick (bool deleteObjects)
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
312 ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
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
360 ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
361 {
362 return insert (indexToInsertAt, newObject.release());
363 }
364
377 void insertArray (int indexToInsertAt,
378 ObjectClass* const* newObjects,
379 int numberOfElements)
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 {
405 std::unique_ptr<ObjectClass> toDelete;
406
407 {
408 const ScopedLockType lock (getLock());
409
410 if (indexToChange < values.size())
411 {
412 if (deleteOldElement)
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
450 ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
451 {
452 return set (indexToChange, newObject.release(), deleteOldElement);
453 }
454
464 template <class OtherArrayType>
465 void addArray (const OtherArrayType& arrayToAddFrom,
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>
476 void addArray (const std::initializer_list<OtherArrayType>& items)
477 {
478 const ScopedLockType lock (getLock());
479 values.addArray (items);
480 }
481
496 template <class OtherArrayType>
497 void addCopiesOf (const OtherArrayType& arrayToAddFrom,
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 {
506 jassertfalse;
507 startIndex = 0;
508 }
509
510 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
511 numElementsToAdd = arrayToAddFrom.size() - startIndex;
512
513 jassert (numElementsToAdd >= 0);
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 {
563 std::unique_ptr<ObjectClass> toDelete;
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
592 ObjectClass* removeAndReturn (int indexToRemove)
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 {
654 Array<ObjectClass*> objectsToDelete;
655
656 if (deleteObjects)
657 objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
658
659 values.removeElements (startIndex, numberToRemove);
660
661 for (auto& o : objectsToDelete)
662 ContainerDeletePolicy<ObjectClass>::destroy (o);
663
664 if ((values.size() << 1) < values.capacity())
666 }
667 }
668
675 void removeLast (int howManyToRemove = 1,
676 bool deleteObjects = true)
677 {
678 const ScopedLockType lock (getLock());
679
680 if (howManyToRemove >= values.size())
681 clear (deleteObjects);
682 else
683 removeRange (values.size() - howManyToRemove, howManyToRemove, deleteObjects);
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>
725 void swapWith (OtherArrayType& otherArray) noexcept
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
751 void ensureStorageAllocated (int minNumElements) noexcept
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 //==============================================================================
805 ArrayBase <ObjectClass*, TypeOfCriticalSectionToUse> values;
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);
815 ContainerDeletePolicy<ObjectClass>::destroy (e);
816 }
817 }
818
819 template <class OtherObjectClass, class OtherCriticalSection>
820 friend class OwnedArray;
821
822 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
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
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
ObjectClass *const * data() const noexcept
int size() const noexcept
ObjectClass * getUnchecked(int index) const noexcept
ObjectClass * set(int indexToChange, ObjectClass *newObject, bool deleteOldElement=true)
ObjectClass * removeAndReturn(int indexToRemove)
ObjectClass * add(std::unique_ptr< ObjectClass > newObject)
ObjectClass * set(int indexToChange, std::unique_ptr< ObjectClass > newObject, bool deleteOldElement=true)
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
bool isEmpty() const noexcept
void swapWith(OtherArrayType &otherArray) noexcept
void remove(int indexToRemove, bool deleteObject=true)
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
void ensureStorageAllocated(int minNumElements) noexcept
ObjectClass * getFirst() const noexcept
void minimiseStorageOverheads() noexcept
void clear(bool deleteObjects=true)
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
int indexOf(const ObjectClass *objectToLookFor) const noexcept
ObjectClass * add(ObjectClass *newObject)
ObjectClass ** begin() noexcept
OwnedArray(OwnedArray< OtherObjectClass, OtherCriticalSection > &&other) noexcept
void swap(int index1, int index2) noexcept
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
ObjectClass * insert(int indexToInsertAt, std::unique_ptr< ObjectClass > newObject)
void clearQuick(bool deleteObjects)
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
ObjectClass *const * begin() const noexcept
ObjectClass *const * end() const noexcept
ObjectClass ** end() noexcept
OwnedArray()=default
OwnedArray & operator=(OwnedArray &&other) noexcept
OwnedArray(OwnedArray &&other) noexcept
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
void move(int currentIndex, int newIndex) noexcept
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
const TypeOfCriticalSectionToUse & getLock() const noexcept
void addArray(const std::initializer_list< OtherArrayType > &items)
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
ObjectClass * operator[](int index) const noexcept
ObjectClass ** getRawDataPointer() noexcept
ObjectClass ** data() noexcept
OwnedArray(const std::initializer_list< ObjectClass * > &items)
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
ObjectClass * getLast() const noexcept
bool contains(const ObjectClass *objectToLookFor) const noexcept