OpenShot Library | OpenShotAudio 0.2.2
juce_OwnedArray.h
1
2/** @weakgroup juce_core-containers
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/** An array designed for holding objects.
32
33 This holds a list of pointers to objects, and will automatically
34 delete the objects when they are removed from the array, or when the
35 array is itself deleted.
36
37 Declare it in the form: OwnedArray<MyObjectClass>
38
39 ..and then add new objects, e.g. myOwnedArray.add (new MyObjectClass());
40
41 After adding objects, they are 'owned' by the array and will be deleted when
42 removed or replaced.
43
44 To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
45 TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
46
47 @see Array, ReferenceCountedArray, StringArray, CriticalSection
48
49 @tags{Core}
50*/
51template <class ObjectClass,
52 class TypeOfCriticalSectionToUse = DummyCriticalSection>
53
55{
56public:
57 //==============================================================================
58 /** Creates an empty array. */
59 OwnedArray() = default;
60
61 /** Deletes the array and also deletes any objects inside it.
62
63 To get rid of the array without deleting its objects, use its
64 clear (false) method before deleting it.
65 */
67 {
68 deleteAllObjects();
69 }
70
71 /** Move constructor. */
72 OwnedArray (OwnedArray&& other) noexcept
73 : values (std::move (other.values))
74 {
75 }
76
77 /** Creates an array from a list of objects. */
78 OwnedArray (const std::initializer_list<ObjectClass*>& items)
79 {
80 addArray (items);
81 }
82
83 /** Move assignment operator. */
84 OwnedArray& operator= (OwnedArray&& other) noexcept
85 {
86 const ScopedLockType lock (getLock());
87 deleteAllObjects();
88 values = std::move (other.values);
89 return *this;
90 }
91
92 /** Converting move constructor. */
93 template <class OtherObjectClass, class OtherCriticalSection>
95 : values (std::move (other.values))
96 {
97 }
98
99 /** Converting move assignment operator. */
100 template <class OtherObjectClass, class OtherCriticalSection>
102 {
103 const ScopedLockType lock (getLock());
104 deleteAllObjects();
105 values = std::move (other.values);
106 return *this;
107 }
108
109 //==============================================================================
110 /** Clears the array, optionally deleting the objects inside it first. */
111 void clear (bool deleteObjects = true)
112 {
113 const ScopedLockType lock (getLock());
114 clearQuick (deleteObjects);
115 values.setAllocatedSize (0);
116 }
117
118 //==============================================================================
119 /** Clears the array, optionally deleting the objects inside it first. */
120 void clearQuick (bool deleteObjects)
121 {
122 const ScopedLockType lock (getLock());
123
124 if (deleteObjects)
125 deleteAllObjects();
126 else
127 values.clear();
128 }
129
130 //==============================================================================
131 /** Returns the number of items currently in the array.
132 @see operator[]
133 */
134 inline int size() const noexcept
135 {
136 return values.size();
137 }
138
139 /** Returns true if the array is empty, false otherwise. */
140 inline bool isEmpty() const noexcept
141 {
142 return size() == 0;
143 }
144
145 /** Returns a pointer to the object at this index in the array.
146
147 If the index is out-of-range, this will return a null pointer, (and
148 it could be null anyway, because it's ok for the array to hold null
149 pointers as well as objects).
150
151 @see getUnchecked
152 */
153 inline ObjectClass* operator[] (int index) const noexcept
154 {
155 const ScopedLockType lock (getLock());
156 return values.getValueWithDefault (index);
157 }
158
159 /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range.
160
161 This is a faster and less safe version of operator[] which doesn't check the index passed in, so
162 it can be used when you're sure the index is always going to be legal.
163 */
164 inline ObjectClass* getUnchecked (int index) const noexcept
165 {
166 const ScopedLockType lock (getLock());
167 return values[index];
168 }
169
170 /** Returns a pointer to the first object in the array.
171
172 This will return a null pointer if the array's empty.
173 @see getLast
174 */
175 inline ObjectClass* getFirst() const noexcept
176 {
177 const ScopedLockType lock (getLock());
178 return values.getFirst();
179 }
180
181 /** Returns a pointer to the last object in the array.
182
183 This will return a null pointer if the array's empty.
184 @see getFirst
185 */
186 inline ObjectClass* getLast() const noexcept
187 {
188 const ScopedLockType lock (getLock());
189 return values.getLast();
190 }
191
192 /** Returns a pointer to the actual array data.
193 This pointer will only be valid until the next time a non-const method
194 is called on the array.
195 */
196 inline ObjectClass** getRawDataPointer() noexcept
197 {
198 return values.begin();
199 }
200
201 //==============================================================================
202 /** Returns a pointer to the first element in the array.
203 This method is provided for compatibility with standard C++ iteration mechanisms.
204 */
205 inline ObjectClass** begin() noexcept
206 {
207 return values.begin();
208 }
209
210 /** Returns a pointer to the first element in the array.
211 This method is provided for compatibility with standard C++ iteration mechanisms.
212 */
213 inline ObjectClass* const* begin() const noexcept
214 {
215 return values.begin();
216 }
217
218 /** Returns a pointer to the element which follows the last element in the array.
219 This method is provided for compatibility with standard C++ iteration mechanisms.
220 */
221 inline ObjectClass** end() noexcept
222 {
223 return values.end();
224 }
225
226 /** Returns a pointer to the element which follows the last element in the array.
227 This method is provided for compatibility with standard C++ iteration mechanisms.
228 */
229 inline ObjectClass* const* end() const noexcept
230 {
231 return values.end();
232 }
233
234 /** Returns a pointer to the first element in the array.
235 This method is provided for compatibility with the standard C++ containers.
236 */
237 inline ObjectClass** data() noexcept
238 {
239 return begin();
240 }
241
242 /** Returns a pointer to the first element in the array.
243 This method is provided for compatibility with the standard C++ containers.
244 */
245 inline ObjectClass* const* data() const noexcept
246 {
247 return begin();
248 }
249
250 //==============================================================================
251 /** Finds the index of an object which might be in the array.
252
253 @param objectToLookFor the object to look for
254 @returns the index at which the object was found, or -1 if it's not found
255 */
256 int indexOf (const ObjectClass* objectToLookFor) const noexcept
257 {
258 const ScopedLockType lock (getLock());
259 auto* e = values.begin();
260
261 for (; e != values.end(); ++e)
262 if (objectToLookFor == *e)
263 return static_cast<int> (e - values.begin());
264
265 return -1;
266 }
267
268 /** Returns true if the array contains a specified object.
269
270 @param objectToLookFor the object to look for
271 @returns true if the object is in the array
272 */
273 bool contains (const ObjectClass* objectToLookFor) const noexcept
274 {
275 const ScopedLockType lock (getLock());
276 auto* e = values.begin();
277
278 for (; e != values.end(); ++e)
279 if (objectToLookFor == *e)
280 return true;
281
282 return false;
283 }
284
285 //==============================================================================
286 /** Appends a new object to the end of the array.
287
288 Note that this object will be deleted by the OwnedArray when it is removed,
289 so be careful not to delete it somewhere else.
290
291 Also be careful not to add the same object to the array more than once,
292 as this will obviously cause deletion of dangling pointers.
293
294 @param newObject the new object to add to the array
295 @returns the new object that was added
296 @see set, insert, addSorted
297 */
298 ObjectClass* add (ObjectClass* newObject)
299 {
300 const ScopedLockType lock (getLock());
301 values.add (newObject);
302 return newObject;
303 }
304
305 /** Appends a new object to the end of the array.
306
307 Note that this object will be deleted by the OwnedArray when it is removed,
308 so be careful not to delete it somewhere else.
309
310 Also be careful not to add the same object to the array more than once,
311 as this will obviously cause deletion of dangling pointers.
312
313 @param newObject the new object to add to the array
314 @returns the new object that was added
315 @see set, insert, addSorted
316 */
317 ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
318 {
319 return add (newObject.release());
320 }
321
322 /** Inserts a new object into the array at the given index.
323
324 Note that this object will be deleted by the OwnedArray when it is removed,
325 so be careful not to delete it somewhere else.
326
327 If the index is less than 0 or greater than the size of the array, the
328 element will be added to the end of the array.
329 Otherwise, it will be inserted into the array, moving all the later elements
330 along to make room.
331
332 Be careful not to add the same object to the array more than once,
333 as this will obviously cause deletion of dangling pointers.
334
335 @param indexToInsertAt the index at which the new element should be inserted
336 @param newObject the new object to add to the array
337 @returns the new object that was added
338 @see add, addSorted, set
339 */
340 ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
341 {
342 const ScopedLockType lock (getLock());
343 values.insert (indexToInsertAt, newObject, 1);
344 return newObject;
345 }
346
347 /** Inserts a new object into the array at the given index.
348
349 Note that this object will be deleted by the OwnedArray when it is removed,
350 so be careful not to delete it somewhere else.
351
352 If the index is less than 0 or greater than the size of the array, the
353 element will be added to the end of the array.
354 Otherwise, it will be inserted into the array, moving all the later elements
355 along to make room.
356
357 Be careful not to add the same object to the array more than once,
358 as this will obviously cause deletion of dangling pointers.
359
360 @param indexToInsertAt the index at which the new element should be inserted
361 @param newObject the new object to add to the array
362 @returns the new object that was added
363 @see add, addSorted, set
364 */
365 ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
366 {
367 return insert (indexToInsertAt, newObject.release());
368 }
369
370 /** Inserts an array of values into this array at a given position.
371
372 If the index is less than 0 or greater than the size of the array, the
373 new elements will be added to the end of the array.
374 Otherwise, they will be inserted into the array, moving all the later elements
375 along to make room.
376
377 @param indexToInsertAt the index at which the first new element should be inserted
378 @param newObjects the new values to add to the array
379 @param numberOfElements how many items are in the array
380 @see insert, add, addSorted, set
381 */
382 void insertArray (int indexToInsertAt,
383 ObjectClass* const* newObjects,
384 int numberOfElements)
385 {
386 if (numberOfElements > 0)
387 {
388 const ScopedLockType lock (getLock());
389 values.insertArray (indexToInsertAt, newObjects, numberOfElements);
390 }
391 }
392
393 /** Replaces an object in the array with a different one.
394
395 If the index is less than zero, this method does nothing.
396 If the index is beyond the end of the array, the new object is added to the end of the array.
397
398 Be careful not to add the same object to the array more than once,
399 as this will obviously cause deletion of dangling pointers.
400
401 @param indexToChange the index whose value you want to change
402 @param newObject the new value to set for this index.
403 @param deleteOldElement whether to delete the object that's being replaced with the new one
404 @see add, insert, remove
405 */
406 ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
407 {
408 if (indexToChange >= 0)
409 {
410 std::unique_ptr<ObjectClass> toDelete;
411
412 {
413 const ScopedLockType lock (getLock());
414
415 if (indexToChange < values.size())
416 {
417 if (deleteOldElement)
418 {
419 toDelete.reset (values[indexToChange]);
420
421 if (toDelete.get() == newObject)
422 toDelete.release();
423 }
424
425 values[indexToChange] = newObject;
426 }
427 else
428 {
429 values.add (newObject);
430 }
431 }
432 }
433 else
434 {
435 jassertfalse; // you're trying to set an object at a negative index, which doesn't have
436 // any effect - but since the object is not being added, it may be leaking..
437 }
438
439 return newObject;
440 }
441
442 /** Replaces an object in the array with a different one.
443
444 If the index is less than zero, this method does nothing.
445 If the index is beyond the end of the array, the new object is added to the end of the array.
446
447 Be careful not to add the same object to the array more than once,
448 as this will obviously cause deletion of dangling pointers.
449
450 @param indexToChange the index whose value you want to change
451 @param newObject the new value to set for this index.
452 @param deleteOldElement whether to delete the object that's being replaced with the new one
453 @see add, insert, remove
454 */
455 ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
456 {
457 return set (indexToChange, newObject.release(), deleteOldElement);
458 }
459
460 /** Adds elements from another array to the end of this array.
461
462 @param arrayToAddFrom the array from which to copy the elements
463 @param startIndex the first element of the other array to start copying from
464 @param numElementsToAdd how many elements to add from the other array. If this
465 value is negative or greater than the number of available elements,
466 all available elements will be copied.
467 @see add
468 */
469 template <class OtherArrayType>
470 void addArray (const OtherArrayType& arrayToAddFrom,
471 int startIndex = 0,
472 int numElementsToAdd = -1)
473 {
474 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
475 const ScopedLockType lock2 (getLock());
476 values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
477 }
478
479 /** Adds elements from another array to the end of this array. */
480 template <typename OtherArrayType>
481 void addArray (const std::initializer_list<OtherArrayType>& items)
482 {
483 const ScopedLockType lock (getLock());
484 values.addArray (items);
485 }
486
487 /** Adds copies of the elements in another array to the end of this array.
488
489 The other array must be either an OwnedArray of a compatible type of object, or an Array
490 containing pointers to the same kind of object. The objects involved must provide
491 a copy constructor, and this will be used to create new copies of each element, and
492 add them to this array.
493
494 @param arrayToAddFrom the array from which to copy the elements
495 @param startIndex the first element of the other array to start copying from
496 @param numElementsToAdd how many elements to add from the other array. If this
497 value is negative or greater than the number of available elements,
498 all available elements will be copied.
499 @see add
500 */
501 template <class OtherArrayType>
502 void addCopiesOf (const OtherArrayType& arrayToAddFrom,
503 int startIndex = 0,
504 int numElementsToAdd = -1)
505 {
506 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
507 const ScopedLockType lock2 (getLock());
508
509 if (startIndex < 0)
510 {
511 jassertfalse;
512 startIndex = 0;
513 }
514
515 if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
516 numElementsToAdd = arrayToAddFrom.size() - startIndex;
517
518 jassert (numElementsToAdd >= 0);
519 values.ensureAllocatedSize (values.size() + numElementsToAdd);
520
521 while (--numElementsToAdd >= 0)
522 values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
523 }
524
525 /** Inserts a new object into the array assuming that the array is sorted.
526
527 This will use a comparator to find the position at which the new object
528 should go. If the array isn't sorted, the behaviour of this
529 method will be unpredictable.
530
531 @param comparator the comparator to use to compare the elements - see the sort method
532 for details about this object's structure
533 @param newObject the new object to insert to the array
534 @returns the index at which the new object was added
535 @see add, sort, indexOfSorted
536 */
537 template <class ElementComparator>
538 int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
539 {
540 // If you pass in an object with a static compareElements() method, this
541 // avoids getting warning messages about the parameter being unused
542 ignoreUnused (comparator);
543
544 const ScopedLockType lock (getLock());
545 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
546 insert (index, newObject);
547 return index;
548 }
549
550 /** Finds the index of an object in the array, assuming that the array is sorted.
551
552 This will use a comparator to do a binary-chop to find the index of the given
553 element, if it exists. If the array isn't sorted, the behaviour of this
554 method will be unpredictable.
555
556 @param comparator the comparator to use to compare the elements - see the sort()
557 method for details about the form this object should take
558 @param objectToLookFor the object to search for
559 @returns the index of the element, or -1 if it's not found
560 @see addSorted, sort
561 */
562 template <typename ElementComparator>
563 int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept
564 {
565 // If you pass in an object with a static compareElements() method, this
566 // avoids getting warning messages about the parameter being unused
567 ignoreUnused (comparator);
568
569 const ScopedLockType lock (getLock());
570 int s = 0, e = values.size();
571
572 while (s < e)
573 {
574 if (comparator.compareElements (objectToLookFor, values[s]) == 0)
575 return s;
576
577 auto halfway = (s + e) / 2;
578
579 if (halfway == s)
580 break;
581
582 if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
583 s = halfway;
584 else
585 e = halfway;
586 }
587
588 return -1;
589 }
590
591 //==============================================================================
592 /** Removes an object from the array.
593
594 This will remove the object at a given index (optionally also
595 deleting it) and move back all the subsequent objects to close the gap.
596 If the index passed in is out-of-range, nothing will happen.
597
598 @param indexToRemove the index of the element to remove
599 @param deleteObject whether to delete the object that is removed
600 @see removeObject, removeRange
601 */
602 void remove (int indexToRemove, bool deleteObject = true)
603 {
604 std::unique_ptr<ObjectClass> toDelete;
605
606 {
607 const ScopedLockType lock (getLock());
608
609 if (isPositiveAndBelow (indexToRemove, values.size()))
610 {
611 auto** e = values.begin() + indexToRemove;
612
613 if (deleteObject)
614 toDelete.reset (*e);
615
616 values.removeElements (indexToRemove, 1);
617 }
618 }
619
620 if ((values.size() << 1) < values.capacity())
622 }
623
624 /** Removes and returns an object from the array without deleting it.
625
626 This will remove the object at a given index and return it, moving back all
627 the subsequent objects to close the gap. If the index passed in is out-of-range,
628 nothing will happen.
629
630 @param indexToRemove the index of the element to remove
631 @see remove, removeObject, removeRange
632 */
633 ObjectClass* removeAndReturn (int indexToRemove)
634 {
635 ObjectClass* removedItem = nullptr;
636 const ScopedLockType lock (getLock());
637
638 if (isPositiveAndBelow (indexToRemove, values.size()))
639 {
640 removedItem = values[indexToRemove];
641
642 values.removeElements (indexToRemove, 1);
643
644 if ((values.size() << 1) < values.capacity())
646 }
647
648 return removedItem;
649 }
650
651 /** Removes a specified object from the array.
652
653 If the item isn't found, no action is taken.
654
655 @param objectToRemove the object to try to remove
656 @param deleteObject whether to delete the object (if it's found)
657 @see remove, removeRange
658 */
659 void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
660 {
661 const ScopedLockType lock (getLock());
662
663 for (int i = 0; i < values.size(); ++i)
664 {
665 if (objectToRemove == values[i])
666 {
667 remove (i, deleteObject);
668 break;
669 }
670 }
671 }
672
673 /** Removes a range of objects from the array.
674
675 This will remove a set of objects, starting from the given index,
676 and move any subsequent elements down to close the gap.
677
678 If the range extends beyond the bounds of the array, it will
679 be safely clipped to the size of the array.
680
681 @param startIndex the index of the first object to remove
682 @param numberToRemove how many objects should be removed
683 @param deleteObjects whether to delete the objects that get removed
684 @see remove, removeObject
685 */
686 void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
687 {
688 const ScopedLockType lock (getLock());
689 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
690 startIndex = jlimit (0, values.size(), startIndex);
691 numberToRemove = endIndex - startIndex;
692
693 if (numberToRemove > 0)
694 {
695 Array<ObjectClass*> objectsToDelete;
696
697 if (deleteObjects)
698 objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
699
700 values.removeElements (startIndex, numberToRemove);
701
702 for (auto& o : objectsToDelete)
704
705 if ((values.size() << 1) < values.capacity())
707 }
708 }
709
710 /** Removes the last n objects from the array.
711
712 @param howManyToRemove how many objects to remove from the end of the array
713 @param deleteObjects whether to also delete the objects that are removed
714 @see remove, removeObject, removeRange
715 */
716 void removeLast (int howManyToRemove = 1,
717 bool deleteObjects = true)
718 {
719 const ScopedLockType lock (getLock());
720
721 if (howManyToRemove >= values.size())
722 clear (deleteObjects);
723 else
724 removeRange (values.size() - howManyToRemove, howManyToRemove, deleteObjects);
725 }
726
727 /** Swaps a pair of objects in the array.
728
729 If either of the indexes passed in is out-of-range, nothing will happen,
730 otherwise the two objects at these positions will be exchanged.
731 */
732 void swap (int index1, int index2) noexcept
733 {
734 const ScopedLockType lock (getLock());
735 values.swap (index1, index2);
736 }
737
738 /** Moves one of the objects to a different position.
739
740 This will move the object to a specified index, shuffling along
741 any intervening elements as required.
742
743 So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
744 move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
745
746 @param currentIndex the index of the object to be moved. If this isn't a
747 valid index, then nothing will be done
748 @param newIndex the index at which you'd like this object to end up. If this
749 is less than zero, it will be moved to the end of the array
750 */
751 void move (int currentIndex, int newIndex) noexcept
752 {
753 if (currentIndex != newIndex)
754 {
755 const ScopedLockType lock (getLock());
756 values.move (currentIndex, newIndex);
757 }
758 }
759
760 /** This swaps the contents of this array with those of another array.
761
762 If you need to exchange two arrays, this is vastly quicker than using copy-by-value
763 because it just swaps their internal pointers.
764 */
765 template <class OtherArrayType>
766 void swapWith (OtherArrayType& otherArray) noexcept
767 {
768 const ScopedLockType lock1 (getLock());
769 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
770 values.swapWith (otherArray.values);
771 }
772
773 //==============================================================================
774 /** Reduces the amount of storage being used by the array.
775
776 Arrays typically allocate slightly more storage than they need, and after
777 removing elements, they may have quite a lot of unused space allocated.
778 This method will reduce the amount of allocated storage to a minimum.
779 */
781 {
782 const ScopedLockType lock (getLock());
783 values.shrinkToNoMoreThan (values.size());
784 }
785
786 /** Increases the array's internal storage to hold a minimum number of elements.
787
788 Calling this before adding a large known number of elements means that
789 the array won't have to keep dynamically resizing itself as the elements
790 are added, and it'll therefore be more efficient.
791 */
792 void ensureStorageAllocated (int minNumElements) noexcept
793 {
794 const ScopedLockType lock (getLock());
795 values.ensureAllocatedSize (minNumElements);
796 }
797
798 //==============================================================================
799 /** Sorts the elements in the array.
800
801 This will use a comparator object to sort the elements into order. The object
802 passed must have a method of the form:
803 @code
804 int compareElements (ElementType* first, ElementType* second);
805 @endcode
806
807 ..and this method must return:
808 - a value of < 0 if the first comes before the second
809 - a value of 0 if the two objects are equivalent
810 - a value of > 0 if the second comes before the first
811
812 To improve performance, the compareElements() method can be declared as static or const.
813
814 @param comparator the comparator to use for comparing elements.
815 @param retainOrderOfEquivalentItems if this is true, then items
816 which the comparator says are equivalent will be
817 kept in the order in which they currently appear
818 in the array. This is slower to perform, but may
819 be important in some cases. If it's false, a faster
820 algorithm is used, but equivalent elements may be
821 rearranged.
822 @see sortArray, indexOfSorted
823 */
824 template <class ElementComparator>
825 void sort (ElementComparator& comparator,
826 bool retainOrderOfEquivalentItems = false) noexcept
827 {
828 // If you pass in an object with a static compareElements() method, this
829 // avoids getting warning messages about the parameter being unused
830 ignoreUnused (comparator);
831
832 const ScopedLockType lock (getLock());
833
834 if (size() > 1)
835 sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
836 }
837
838 //==============================================================================
839 /** Returns the CriticalSection that locks this array.
840 To lock, you can call getLock().enter() and getLock().exit(), or preferably use
841 an object of ScopedLockType as an RAII lock for it.
842 */
843 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
844
845 /** Returns the type of scoped lock to use for locking this array */
846 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
847
848 //==============================================================================
849 #ifndef DOXYGEN
850 // Note that the swapWithArray method has been replaced by a more flexible templated version,
851 // and renamed "swapWith" to be more consistent with the names used in other classes.
852 JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
853 #endif
854
855private:
856 //==============================================================================
858
859 void deleteAllObjects()
860 {
861 auto i = values.size();
862
863 while (--i >= 0)
864 {
865 auto* e = values[i];
866 values.removeElements (i, 1);
868 }
869 }
870
871 template <class OtherObjectClass, class OtherCriticalSection>
872 friend class OwnedArray;
873
874 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
875};
876
877} // namespace juce
878
879/** @}*/
A basic object container.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:60
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:587
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.
Used by container classes as an indirect way to delete an object of a particular type.