OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_OwnedArray.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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>
49
51{
52public:
53 //==============================================================================
55 OwnedArray() = default;
56
63 {
64 deleteAllObjects();
65 }
66
69 : values (std::move (other.values))
70 {
71 }
72
74 OwnedArray (const std::initializer_list<ObjectClass*>& items)
75 {
76 addArray (items);
77 }
78
81 {
82 const ScopedLockType lock (getLock());
83 deleteAllObjects();
84 values = std::move (other.values);
85 return *this;
86 }
87
89 template <class OtherObjectClass, class OtherCriticalSection>
94
96 template <class OtherObjectClass, class OtherCriticalSection>
98 {
99 const ScopedLockType lock (getLock());
100 deleteAllObjects();
101 values = std::move (other.values);
102 return *this;
103 }
104
105 //==============================================================================
107 void clear (bool deleteObjects = true)
108 {
109 const ScopedLockType lock (getLock());
111 values.setAllocatedSize (0);
112 }
113
114 //==============================================================================
117 {
118 const ScopedLockType lock (getLock());
119
120 if (deleteObjects)
121 deleteAllObjects();
122 else
123 values.clear();
124 }
125
126 //==============================================================================
130 inline int size() const noexcept
131 {
132 return values.size();
133 }
134
136 inline bool isEmpty() const noexcept
137 {
138 return size() == 0;
139 }
140
149 inline ObjectClass* operator[] (int index) const noexcept
150 {
151 const ScopedLockType lock (getLock());
152 return values.getValueWithDefault (index);
153 }
154
160 inline ObjectClass* getUnchecked (int index) const noexcept
161 {
162 const ScopedLockType lock (getLock());
163 return values[index];
164 }
165
171 inline ObjectClass* getFirst() const noexcept
172 {
173 const ScopedLockType lock (getLock());
174 return values.getFirst();
175 }
176
182 inline ObjectClass* getLast() const noexcept
183 {
184 const ScopedLockType lock (getLock());
185 return values.getLast();
186 }
187
192 inline ObjectClass** getRawDataPointer() noexcept
193 {
194 return values.begin();
195 }
196
197 //==============================================================================
201 inline ObjectClass** begin() noexcept
202 {
203 return values.begin();
204 }
205
209 inline ObjectClass* const* begin() const noexcept
210 {
211 return values.begin();
212 }
213
217 inline ObjectClass** end() noexcept
218 {
219 return values.end();
220 }
221
225 inline ObjectClass* const* end() const noexcept
226 {
227 return values.end();
228 }
229
233 inline ObjectClass** data() noexcept
234 {
235 return begin();
236 }
237
241 inline ObjectClass* const* data() const noexcept
242 {
243 return begin();
244 }
245
246 //==============================================================================
252 int indexOf (const ObjectClass* objectToLookFor) const noexcept
253 {
254 const ScopedLockType lock (getLock());
255 auto* e = values.begin();
256
257 for (; e != values.end(); ++e)
258 if (objectToLookFor == *e)
259 return static_cast<int> (e - values.begin());
260
261 return -1;
262 }
263
269 bool contains (const ObjectClass* objectToLookFor) const noexcept
270 {
271 const ScopedLockType lock (getLock());
272 auto* e = values.begin();
273
274 for (; e != values.end(); ++e)
275 if (objectToLookFor == *e)
276 return true;
277
278 return false;
279 }
280
281 //==============================================================================
294 ObjectClass* add (ObjectClass* newObject)
295 {
296 const ScopedLockType lock (getLock());
297 values.add (newObject);
298 return newObject;
299 }
300
313 ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
314 {
315 return add (newObject.release());
316 }
317
336 ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
337 {
338 const ScopedLockType lock (getLock());
339 values.insert (indexToInsertAt, newObject, 1);
340 return newObject;
341 }
342
361 ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
362 {
363 return insert (indexToInsertAt, newObject.release());
364 }
365
379 ObjectClass* const* newObjects,
381 {
382 if (numberOfElements > 0)
383 {
384 const ScopedLockType lock (getLock());
385 values.insertArray (indexToInsertAt, newObjects, numberOfElements);
386 }
387 }
388
402 ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
403 {
404 if (indexToChange >= 0)
405 {
406 std::unique_ptr<ObjectClass> toDelete;
407
408 {
409 const ScopedLockType lock (getLock());
410
411 if (indexToChange < values.size())
412 {
414 {
415 toDelete.reset (values[indexToChange]);
416
417 if (toDelete.get() == newObject)
418 toDelete.release();
419 }
420
421 values[indexToChange] = newObject;
422 }
423 else
424 {
425 values.add (newObject);
426 }
427 }
428 }
429 else
430 {
431 jassertfalse; // you're trying to set an object at a negative index, which doesn't have
432 // any effect - but since the object is not being added, it may be leaking..
433 }
434
435 return newObject;
436 }
437
451 ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
452 {
453 return set (indexToChange, newObject.release(), deleteOldElement);
454 }
455
465 template <class OtherArrayType>
467 int startIndex = 0,
468 int numElementsToAdd = -1)
469 {
470 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
471 const ScopedLockType lock2 (getLock());
472 values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
473 }
474
476 template <typename OtherArrayType>
477 void addArray (const std::initializer_list<OtherArrayType>& items)
478 {
479 const ScopedLockType lock (getLock());
480 values.addArray (items);
481 }
482
497 template <class OtherArrayType>
499 int startIndex = 0,
500 int numElementsToAdd = -1)
501 {
502 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
503 const ScopedLockType lock2 (getLock());
504
505 if (startIndex < 0)
506 {
507 jassertfalse;
508 startIndex = 0;
509 }
510
512 numElementsToAdd = arrayToAddFrom.size() - startIndex;
513
514 jassert (numElementsToAdd >= 0);
515 values.ensureAllocatedSize (values.size() + numElementsToAdd);
516
517 while (--numElementsToAdd >= 0)
518 values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
519 }
520
533 template <class ElementComparator>
534 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
535 {
536 // If you pass in an object with a static compareElements() method, this
537 // avoids getting warning messages about the parameter being unused
538 ignoreUnused (comparator);
539
540 const ScopedLockType lock (getLock());
541 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
542 insert (index, newObject);
543 return index;
544 }
545
558 template <typename ElementComparator>
559 int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept
560 {
561 // If you pass in an object with a static compareElements() method, this
562 // avoids getting warning messages about the parameter being unused
563 ignoreUnused (comparator);
564
565 const ScopedLockType lock (getLock());
566 int s = 0, e = values.size();
567
568 while (s < e)
569 {
570 if (comparator.compareElements (objectToLookFor, values[s]) == 0)
571 return s;
572
573 auto halfway = (s + e) / 2;
574
575 if (halfway == s)
576 break;
577
578 if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
579 s = halfway;
580 else
581 e = halfway;
582 }
583
584 return -1;
585 }
586
587 //==============================================================================
598 void remove (int indexToRemove, bool deleteObject = true)
599 {
600 std::unique_ptr<ObjectClass> toDelete;
601
602 {
603 const ScopedLockType lock (getLock());
604
605 if (isPositiveAndBelow (indexToRemove, values.size()))
606 {
607 auto** e = values.begin() + indexToRemove;
608
609 if (deleteObject)
610 toDelete.reset (*e);
611
612 values.removeElements (indexToRemove, 1);
613 }
614 }
615
616 if ((values.size() << 1) < values.capacity())
618 }
619
630 {
631 ObjectClass* removedItem = nullptr;
632 const ScopedLockType lock (getLock());
633
634 if (isPositiveAndBelow (indexToRemove, values.size()))
635 {
636 removedItem = values[indexToRemove];
637
638 values.removeElements (indexToRemove, 1);
639
640 if ((values.size() << 1) < values.capacity())
642 }
643
644 return removedItem;
645 }
646
655 void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
656 {
657 const ScopedLockType lock (getLock());
658
659 for (int i = 0; i < values.size(); ++i)
660 {
661 if (objectToRemove == values[i])
662 {
663 remove (i, deleteObject);
664 break;
665 }
666 }
667 }
668
682 void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
683 {
684 const ScopedLockType lock (getLock());
685 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
686 startIndex = jlimit (0, values.size(), startIndex);
687 numberToRemove = endIndex - startIndex;
688
689 if (numberToRemove > 0)
690 {
692
693 if (deleteObjects)
694 objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
695
696 values.removeElements (startIndex, numberToRemove);
697
698 for (auto& o : objectsToDelete)
700
701 if ((values.size() << 1) < values.capacity())
703 }
704 }
705
713 bool deleteObjects = true)
714 {
715 const ScopedLockType lock (getLock());
716
717 if (howManyToRemove >= values.size())
719 else
721 }
722
728 void swap (int index1, int index2) noexcept
729 {
730 const ScopedLockType lock (getLock());
731 values.swap (index1, index2);
732 }
733
747 void move (int currentIndex, int newIndex) noexcept
748 {
749 if (currentIndex != newIndex)
750 {
751 const ScopedLockType lock (getLock());
752 values.move (currentIndex, newIndex);
753 }
754 }
755
761 template <class OtherArrayType>
763 {
764 const ScopedLockType lock1 (getLock());
765 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
766 values.swapWith (otherArray.values);
767 }
768
769 //==============================================================================
777 {
778 const ScopedLockType lock (getLock());
779 values.shrinkToNoMoreThan (values.size());
780 }
781
789 {
790 const ScopedLockType lock (getLock());
791 values.ensureAllocatedSize (minNumElements);
792 }
793
794 //==============================================================================
820 template <class ElementComparator>
821 void sort (ElementComparator& comparator,
823 {
824 // If you pass in an object with a static compareElements() method, this
825 // avoids getting warning messages about the parameter being unused
826 ignoreUnused (comparator);
827
828 const ScopedLockType lock (getLock());
829
830 if (size() > 1)
831 sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
832 }
833
834 //==============================================================================
839 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
840
842 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
843
844 //==============================================================================
845 #ifndef DOXYGEN
846 // Note that the swapWithArray method has been replaced by a more flexible templated version,
847 // and renamed "swapWith" to be more consistent with the names used in other classes.
848 JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
849 #endif
850
851private:
852 //==============================================================================
853 ArrayBase <ObjectClass*, TypeOfCriticalSectionToUse> values;
854
855 void deleteAllObjects()
856 {
857 auto i = values.size();
858
859 while (--i >= 0)
860 {
861 auto* e = values[i];
862 values.removeElements (i, 1);
864 }
865 }
866
867 template <class OtherObjectClass, class OtherCriticalSection>
868 friend class OwnedArray;
869
870 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
871};
872
873} // namespace juce
ElementType getUnchecked(int index) const
Definition juce_Array.h:252
const TypeOfCriticalSectionToUse & getLock() const noexcept
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
int size() const noexcept
Definition juce_Array.h:215
ElementType * begin() noexcept
Definition juce_Array.h:328
ElementType * end() noexcept
Definition juce_Array.h:344
void add(const ElementType &newElement)
Definition juce_Array.h:418
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