OpenShot Library | OpenShotAudio 0.2.2
juce_Array.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/**
32 Holds a resizable array of primitive or copy-by-value objects.
33
34 Examples of arrays are: Array<int>, Array<Rectangle> or Array<MyClass*>
35
36 The Array class can be used to hold simple, non-polymorphic objects as well as primitive types - to
37 do so, the class must fulfill these requirements:
38 - it must have a copy constructor and assignment operator
39 - it must be able to be relocated in memory by a memcpy without this causing any problems - so
40 objects whose functionality relies on external pointers or references to themselves can not be used.
41
42 You can of course have an array of pointers to any kind of object, e.g. Array<MyClass*>, but if
43 you do this, the array doesn't take any ownership of the objects - see the OwnedArray class or the
44 ReferenceCountedArray class for more powerful ways of holding lists of objects.
45
46 For holding lists of strings, you can use Array<String>, but it's usually better to use the
47 specialised class StringArray, which provides more useful functions.
48
49 To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
50 TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
51
52 @see OwnedArray, ReferenceCountedArray, StringArray, CriticalSection
53
54 @tags{Core}
55*/
56template <typename ElementType,
57 typename TypeOfCriticalSectionToUse = DummyCriticalSection,
58 int minimumAllocatedSize = 0>
59class Array
60{
61private:
62 using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
63
64public:
65 //==============================================================================
66 /** Creates an empty array. */
67 Array() = default;
68
69 /** Creates a copy of another array.
70 @param other the array to copy
71 */
72 Array (const Array& other)
73 {
74 const ScopedLockType lock (other.getLock());
75 values.addArray (other.values.begin(), other.values.size());
76 }
77
78 Array (Array&& other) noexcept
79 : values (std::move (other.values))
80 {
81 }
82
83 /** Initalises from a null-terminated raw array of values.
84 @param data the data to copy from
85 */
86 template <typename TypeToCreateFrom>
87 explicit Array (const TypeToCreateFrom* data)
88 {
89 while (*values != TypeToCreateFrom())
90 add (*data++);
91 }
92
93 /** Initalises from a raw array of values.
94 @param data the data to copy from
95 @param numValues the number of values in the array
96 */
97 template <typename TypeToCreateFrom>
98 Array (const TypeToCreateFrom* data, int numValues)
99 {
100 values.addArray (data, numValues);
101 }
102
103 /** Initalises an Array of size 1 containing a single element. */
104 Array (const ElementType& singleElementToAdd)
105 {
106 add (singleElementToAdd);
107 }
108
109 /** Initalises an Array of size 1 containing a single element. */
110 Array (ElementType&& singleElementToAdd)
111 {
112 add (std::move (singleElementToAdd));
113 }
114
115 /** Initalises an Array from a list of items. */
116 template <typename... OtherElements>
117 Array (const ElementType& firstNewElement, OtherElements... otherElements)
118 {
119 values.add (firstNewElement, otherElements...);
120 }
121
122 /** Initalises an Array from a list of items. */
123 template <typename... OtherElements>
124 Array (ElementType&& firstNewElement, OtherElements... otherElements)
125 {
126 values.add (std::move (firstNewElement), otherElements...);
127 }
128
129 template <typename TypeToCreateFrom>
130 Array (const std::initializer_list<TypeToCreateFrom>& items)
131 {
132 addArray (items);
133 }
134
135 /** Destructor. */
136 ~Array() = default;
137
138 /** Copies another array.
139 @param other the array to copy
140 */
141 Array& operator= (const Array& other)
142 {
143 if (this != &other)
144 {
145 auto otherCopy (other);
146 swapWith (otherCopy);
147 }
148
149 return *this;
150 }
151
152 Array& operator= (Array&& other) noexcept
153 {
154 const ScopedLockType lock (getLock());
155 values = std::move (other.values);
156 return *this;
157 }
158
159 //==============================================================================
160 /** Compares this array to another one.
161 Two arrays are considered equal if they both contain the same set of
162 elements, in the same order.
163 @param other the other array to compare with
164 */
165 template <class OtherArrayType>
166 bool operator== (const OtherArrayType& other) const
167 {
168 const ScopedLockType lock (getLock());
169 const typename OtherArrayType::ScopedLockType lock2 (other.getLock());
170 return values == other;
171 }
172
173 /** Compares this array to another one.
174 Two arrays are considered equal if they both contain the same set of
175 elements, in the same order.
176 @param other the other array to compare with
177 */
178 template <class OtherArrayType>
179 bool operator!= (const OtherArrayType& other) const
180 {
181 return ! operator== (other);
182 }
183
184 //==============================================================================
185 /** Removes all elements from the array.
186 This will remove all the elements, and free any storage that the array is
187 using. To clear the array without freeing the storage, use the clearQuick()
188 method instead.
189
190 @see clearQuick
191 */
192 void clear()
193 {
194 const ScopedLockType lock (getLock());
195 clearQuick();
196 values.setAllocatedSize (0);
197 }
198
199 /** Removes all elements from the array without freeing the array's allocated storage.
200 @see clear
201 */
203 {
204 const ScopedLockType lock (getLock());
205 values.clear();
206 }
207
208 /** Fills the Array with the provided value. */
209 void fill (const ParameterType& newValue) noexcept
210 {
211 const ScopedLockType lock (getLock());
212
213 for (auto& e : *this)
214 e = newValue;
215 }
216
217 //==============================================================================
218 /** Returns the current number of elements in the array. */
219 inline int size() const noexcept
220 {
221 const ScopedLockType lock (getLock());
222 return values.size();
223 }
224
225 /** Returns true if the array is empty, false otherwise. */
226 inline bool isEmpty() const noexcept
227 {
228 return size() == 0;
229 }
230
231 /** Returns one of the elements in the array.
232 If the index passed in is beyond the range of valid elements, this
233 will return a default value.
234
235 If you're certain that the index will always be a valid element, you
236 can call getUnchecked() instead, which is faster.
237
238 @param index the index of the element being requested (0 is the first element in the array)
239 @see getUnchecked, getFirst, getLast
240 */
241 ElementType operator[] (int index) const
242 {
243 const ScopedLockType lock (getLock());
244 return values.getValueWithDefault (index);
245 }
246
247 /** Returns one of the elements in the array, without checking the index passed in.
248
249 Unlike the operator[] method, this will try to return an element without
250 checking that the index is within the bounds of the array, so should only
251 be used when you're confident that it will always be a valid index.
252
253 @param index the index of the element being requested (0 is the first element in the array)
254 @see operator[], getFirst, getLast
255 */
256 inline ElementType getUnchecked (int index) const
257 {
258 const ScopedLockType lock (getLock());
259 return values[index];
260 }
261
262 /** Returns a direct reference to one of the elements in the array, without checking the index passed in.
263
264 This is like getUnchecked, but returns a direct reference to the element, so that
265 you can alter it directly. Obviously this can be dangerous, so only use it when
266 absolutely necessary.
267
268 @param index the index of the element being requested (0 is the first element in the array)
269 @see operator[], getFirst, getLast
270 */
271 inline ElementType& getReference (int index) noexcept
272 {
273 const ScopedLockType lock (getLock());
274 return values[index];
275 }
276
277 /** Returns a direct reference to one of the elements in the array, without checking the index passed in.
278
279 This is like getUnchecked, but returns a direct reference to the element. Obviously
280 this can be dangerous, so only use it when absolutely necessary.
281
282 @param index the index of the element being requested (0 is the first element in the array)
283 @see operator[], getFirst, getLast
284 */
285 inline const ElementType& getReference (int index) const noexcept
286 {
287 const ScopedLockType lock (getLock());
288 return values[index];
289 }
290
291 /** Returns the first element in the array, or a default value if the array is empty.
292 @see operator[], getUnchecked, getLast
293 */
294 inline ElementType getFirst() const noexcept
295 {
296 const ScopedLockType lock (getLock());
297 return values.getFirst();
298 }
299
300 /** Returns the last element in the array, or a default value if the array is empty.
301
302 @see operator[], getUnchecked, getFirst
303 */
304 inline ElementType getLast() const noexcept
305 {
306 const ScopedLockType lock (getLock());
307 return values.getLast();
308 }
309
310 /** Returns a pointer to the actual array data.
311 This pointer will only be valid until the next time a non-const method
312 is called on the array.
313 */
314 inline ElementType* getRawDataPointer() noexcept
315 {
316 return values.begin();
317 }
318
319 /** Returns a pointer to the actual array data.
320 This pointer will only be valid until the next time a non-const method
321 is called on the array.
322 */
323 inline const ElementType* getRawDataPointer() const noexcept
324 {
325 return values.begin();
326 }
327
328 //==============================================================================
329 /** Returns a pointer to the first element in the array.
330 This method is provided for compatibility with standard C++ iteration mechanisms.
331 */
332 inline ElementType* begin() noexcept
333 {
334 return values.begin();
335 }
336
337 /** Returns a pointer to the first element in the array.
338 This method is provided for compatibility with standard C++ iteration mechanisms.
339 */
340 inline const ElementType* begin() const noexcept
341 {
342 return values.begin();
343 }
344
345 /** Returns a pointer to the element which follows the last element in the array.
346 This method is provided for compatibility with standard C++ iteration mechanisms.
347 */
348 inline ElementType* end() noexcept
349 {
350 return values.end();
351 }
352
353 /** Returns a pointer to the element which follows the last element in the array.
354 This method is provided for compatibility with standard C++ iteration mechanisms.
355 */
356 inline const ElementType* end() const noexcept
357 {
358 return values.end();
359 }
360
361 /** Returns a pointer to the first element in the array.
362 This method is provided for compatibility with the standard C++ containers.
363 */
364 inline ElementType* data() noexcept
365 {
366 return begin();
367 }
368
369 /** Returns a pointer to the first element in the array.
370 This method is provided for compatibility with the standard C++ containers.
371 */
372 inline const ElementType* data() const noexcept
373 {
374 return begin();
375 }
376
377 //==============================================================================
378 /** Finds the index of the first element which matches the value passed in.
379
380 This will search the array for the given object, and return the index
381 of its first occurrence. If the object isn't found, the method will return -1.
382
383 @param elementToLookFor the value or object to look for
384 @returns the index of the object, or -1 if it's not found
385 */
386 int indexOf (ParameterType elementToLookFor) const
387 {
388 const ScopedLockType lock (getLock());
389 auto e = values.begin();
390 auto endPtr = values.end();
391
392 for (; e != endPtr; ++e)
393 if (elementToLookFor == *e)
394 return static_cast<int> (e - values.begin());
395
396 return -1;
397 }
398
399 /** Returns true if the array contains at least one occurrence of an object.
400
401 @param elementToLookFor the value or object to look for
402 @returns true if the item is found
403 */
404 bool contains (ParameterType elementToLookFor) const
405 {
406 const ScopedLockType lock (getLock());
407 auto e = values.begin();
408 auto endPtr = values.end();
409
410 for (; e != endPtr; ++e)
411 if (elementToLookFor == *e)
412 return true;
413
414 return false;
415 }
416
417 //==============================================================================
418 /** Appends a new element at the end of the array.
419 @param newElement the new object to add to the array
420 @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
421 */
422 void add (const ElementType& newElement)
423 {
424 const ScopedLockType lock (getLock());
425 values.add (newElement);
426 }
427
428 /** Appends a new element at the end of the array.
429 @param newElement the new object to add to the array
430 @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
431 */
432 void add (ElementType&& newElement)
433 {
434 const ScopedLockType lock (getLock());
435 values.add (std::move (newElement));
436 }
437
438 /** Appends multiple new elements at the end of the array. */
439 template <typename... OtherElements>
440 void add (const ElementType& firstNewElement, OtherElements... otherElements)
441 {
442 const ScopedLockType lock (getLock());
443 values.add (firstNewElement, otherElements...);
444 }
445
446 /** Appends multiple new elements at the end of the array. */
447 template <typename... OtherElements>
448 void add (ElementType&& firstNewElement, OtherElements... otherElements)
449 {
450 const ScopedLockType lock (getLock());
451 values.add (std::move (firstNewElement), otherElements...);
452 }
453
454 /** Inserts a new element into the array at a given position.
455
456 If the index is less than 0 or greater than the size of the array, the
457 element will be added to the end of the array.
458 Otherwise, it will be inserted into the array, moving all the later elements
459 along to make room.
460
461 @param indexToInsertAt the index at which the new element should be
462 inserted (pass in -1 to add it to the end)
463 @param newElement the new object to add to the array
464 @see add, addSorted, addUsingDefaultSort, set
465 */
466 void insert (int indexToInsertAt, ParameterType newElement)
467 {
468 const ScopedLockType lock (getLock());
469 values.insert (indexToInsertAt, newElement, 1);
470 }
471
472 /** Inserts multiple copies of an element into the array at a given position.
473
474 If the index is less than 0 or greater than the size of the array, the
475 element will be added to the end of the array.
476 Otherwise, it will be inserted into the array, moving all the later elements
477 along to make room.
478
479 @param indexToInsertAt the index at which the new element should be inserted
480 @param newElement the new object to add to the array
481 @param numberOfTimesToInsertIt how many copies of the value to insert
482 @see insert, add, addSorted, set
483 */
484 void insertMultiple (int indexToInsertAt, ParameterType newElement,
485 int numberOfTimesToInsertIt)
486 {
487 if (numberOfTimesToInsertIt > 0)
488 {
489 const ScopedLockType lock (getLock());
490 values.insert (indexToInsertAt, newElement, numberOfTimesToInsertIt);
491 }
492 }
493
494 /** Inserts an array of values into this array at a given position.
495
496 If the index is less than 0 or greater than the size of the array, the
497 new elements will be added to the end of the array.
498 Otherwise, they will be inserted into the array, moving all the later elements
499 along to make room.
500
501 @param indexToInsertAt the index at which the first new element should be inserted
502 @param newElements the new values to add to the array
503 @param numberOfElements how many items are in the array
504 @see insert, add, addSorted, set
505 */
506 void insertArray (int indexToInsertAt,
507 const ElementType* newElements,
508 int numberOfElements)
509 {
510 if (numberOfElements > 0)
511 {
512 const ScopedLockType lock (getLock());
513 values.insertArray (indexToInsertAt, newElements, numberOfElements);
514 }
515 }
516
517 /** Appends a new element at the end of the array as long as the array doesn't
518 already contain it.
519
520 If the array already contains an element that matches the one passed in, nothing
521 will be done.
522
523 @param newElement the new object to add to the array
524 @return true if the element was added to the array; false otherwise.
525 */
526 bool addIfNotAlreadyThere (ParameterType newElement)
527 {
528 const ScopedLockType lock (getLock());
529
530 if (contains (newElement))
531 return false;
532
533 add (newElement);
534 return true;
535 }
536
537 /** Replaces an element with a new value.
538
539 If the index is less than zero, this method does nothing.
540 If the index is beyond the end of the array, the item is added to the end of the array.
541
542 @param indexToChange the index whose value you want to change
543 @param newValue the new value to set for this index.
544 @see add, insert
545 */
546 void set (int indexToChange, ParameterType newValue)
547 {
548 if (indexToChange >= 0)
549 {
550 const ScopedLockType lock (getLock());
551
552 if (indexToChange < values.size())
553 values[indexToChange] = newValue;
554 else
555 values.add (newValue);
556 }
557 else
558 {
559 jassertfalse;
560 }
561 }
562
563 /** Replaces an element with a new value without doing any bounds-checking.
564
565 This just sets a value directly in the array's internal storage, so you'd
566 better make sure it's in range!
567
568 @param indexToChange the index whose value you want to change
569 @param newValue the new value to set for this index.
570 @see set, getUnchecked
571 */
572 void setUnchecked (int indexToChange, ParameterType newValue)
573 {
574 const ScopedLockType lock (getLock());
575 jassert (isPositiveAndBelow (indexToChange, values.size()));
576 values[indexToChange] = newValue;
577 }
578
579 /** Adds elements from an array to the end of this array.
580
581 @param elementsToAdd an array of some kind of object from which elements
582 can be constructed.
583 @param numElementsToAdd how many elements are in this other array
584 @see add
585 */
586 template <typename Type>
587 void addArray (const Type* elementsToAdd, int numElementsToAdd)
588 {
589 const ScopedLockType lock (getLock());
590
591 if (numElementsToAdd > 0)
592 values.addArray (elementsToAdd, numElementsToAdd);
593 }
594
595 template <typename TypeToCreateFrom>
596 void addArray (const std::initializer_list<TypeToCreateFrom>& items)
597 {
598 const ScopedLockType lock (getLock());
599 values.addArray (items);
600 }
601
602 /** Adds elements from a null-terminated array of pointers to the end of this array.
603
604 @param elementsToAdd an array of pointers to some kind of object from which elements
605 can be constructed. This array must be terminated by a nullptr
606 @see addArray
607 */
608 template <typename Type>
609 void addNullTerminatedArray (const Type* const* elementsToAdd)
610 {
611 int num = 0;
612
613 for (auto e = elementsToAdd; *e != nullptr; ++e)
614 ++num;
615
616 addArray (elementsToAdd, num);
617 }
618
619 /** This swaps the contents of this array with those of another array.
620
621 If you need to exchange two arrays, this is vastly quicker than using copy-by-value
622 because it just swaps their internal pointers.
623 */
624 template <class OtherArrayType>
625 void swapWith (OtherArrayType& otherArray) noexcept
626 {
627 const ScopedLockType lock1 (getLock());
628 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
629 values.swapWith (otherArray.values);
630 }
631
632 /** Adds elements from another array to the end of this array.
633
634 @param arrayToAddFrom the array from which to copy the elements
635 @see add
636 */
637 template <class OtherArrayType>
638 void addArray (const OtherArrayType& arrayToAddFrom)
639 {
640 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
641 const ScopedLockType lock2 (getLock());
642
643 values.addArray (arrayToAddFrom);
644 }
645
646 /** Adds elements from another array to the end of this array.
647
648 @param arrayToAddFrom the array from which to copy the elements
649 @param startIndex the first element of the other array to start copying from
650 @param numElementsToAdd how many elements to add from the other array. If this
651 value is negative or greater than the number of available elements,
652 all available elements will be copied.
653 @see add
654 */
655 template <class OtherArrayType>
656 typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type
657 addArray (const OtherArrayType& arrayToAddFrom,
658 int startIndex,
659 int numElementsToAdd = -1)
660 {
661 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
662 const ScopedLockType lock2 (getLock());
663
664 values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
665 }
666
667 /** This will enlarge or shrink the array to the given number of elements, by adding
668 or removing items from its end.
669
670 If the array is smaller than the given target size, empty elements will be appended
671 until its size is as specified. If its size is larger than the target, items will be
672 removed from its end to shorten it.
673 */
674 void resize (int targetNumItems)
675 {
676 jassert (targetNumItems >= 0);
677 auto numToAdd = targetNumItems - values.size();
678
679 if (numToAdd > 0)
680 insertMultiple (values.size(), ElementType(), numToAdd);
681 else if (numToAdd < 0)
682 removeRange (targetNumItems, -numToAdd);
683 }
684
685 /** Inserts a new element into the array, assuming that the array is sorted.
686
687 This will use a comparator to find the position at which the new element
688 should go. If the array isn't sorted, the behaviour of this
689 method will be unpredictable.
690
691 @param comparator the comparator to use to compare the elements - see the sort()
692 method for details about the form this object should take
693 @param newElement the new element to insert to the array
694 @returns the index at which the new item was added
695 @see addUsingDefaultSort, add, sort
696 */
697 template <class ElementComparator>
698 int addSorted (ElementComparator& comparator, ParameterType newElement)
699 {
700 const ScopedLockType lock (getLock());
701 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newElement, 0, values.size());
702 insert (index, newElement);
703 return index;
704 }
705
706 /** Inserts a new element into the array, assuming that the array is sorted.
707
708 This will use the DefaultElementComparator class for sorting, so your ElementType
709 must be suitable for use with that class. If the array isn't sorted, the behaviour of this
710 method will be unpredictable.
711
712 @param newElement the new element to insert to the array
713 @see addSorted, sort
714 */
715 void addUsingDefaultSort (ParameterType newElement)
716 {
718 addSorted (comparator, newElement);
719 }
720
721 /** Finds the index of an element in the array, assuming that the array is sorted.
722
723 This will use a comparator to do a binary-chop to find the index of the given
724 element, if it exists. If the array isn't sorted, the behaviour of this
725 method will be unpredictable.
726
727 @param comparator the comparator to use to compare the elements - see the sort()
728 method for details about the form this object should take
729 @param elementToLookFor the element to search for
730 @returns the index of the element, or -1 if it's not found
731 @see addSorted, sort
732 */
733 template <typename ElementComparator, typename TargetValueType>
734 int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const
735 {
736 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
737 // avoids getting warning messages about the parameter being unused
738
739 const ScopedLockType lock (getLock());
740
741 for (int s = 0, e = values.size();;)
742 {
743 if (s >= e)
744 return -1;
745
746 if (comparator.compareElements (elementToLookFor, values[s]) == 0)
747 return s;
748
749 auto halfway = (s + e) / 2;
750
751 if (halfway == s)
752 return -1;
753
754 if (comparator.compareElements (elementToLookFor, values[halfway]) >= 0)
755 s = halfway;
756 else
757 e = halfway;
758 }
759 }
760
761 //==============================================================================
762 /** Removes an element from the array.
763
764 This will remove the element at a given index, and move back
765 all the subsequent elements to close the gap.
766 If the index passed in is out-of-range, nothing will happen.
767
768 @param indexToRemove the index of the element to remove
769 @see removeAndReturn, removeFirstMatchingValue, removeAllInstancesOf, removeRange
770 */
771 void remove (int indexToRemove)
772 {
773 const ScopedLockType lock (getLock());
774
775 if (isPositiveAndBelow (indexToRemove, values.size()))
776 removeInternal (indexToRemove);
777 }
778
779 /** Removes an element from the array.
780
781 This will remove the element at a given index, and move back
782 all the subsequent elements to close the gap.
783 If the index passed in is out-of-range, nothing will happen.
784
785 @param indexToRemove the index of the element to remove
786 @returns the element that has been removed
787 @see removeFirstMatchingValue, removeAllInstancesOf, removeRange
788 */
789 ElementType removeAndReturn (int indexToRemove)
790 {
791 const ScopedLockType lock (getLock());
792
793 if (isPositiveAndBelow (indexToRemove, values.size()))
794 {
795 ElementType removed (values[indexToRemove]);
796 removeInternal (indexToRemove);
797 return removed;
798 }
799
800 return ElementType();
801 }
802
803 /** Removes an element from the array.
804
805 This will remove the element pointed to by the given iterator,
806 and move back all the subsequent elements to close the gap.
807 If the iterator passed in does not point to an element within the
808 array, behaviour is undefined.
809
810 @param elementToRemove a pointer to the element to remove
811 @see removeFirstMatchingValue, removeAllInstancesOf, removeRange, removeIf
812 */
813 void remove (const ElementType* elementToRemove)
814 {
815 jassert (elementToRemove != nullptr);
816 const ScopedLockType lock (getLock());
817
818 jassert (values.begin() != nullptr);
819 auto indexToRemove = (int) (elementToRemove - values.begin());
820
821 if (! isPositiveAndBelow (indexToRemove, values.size()))
822 {
823 jassertfalse;
824 return;
825 }
826
827 removeInternal (indexToRemove);
828 }
829
830 /** Removes an item from the array.
831
832 This will remove the first occurrence of the given element from the array.
833 If the item isn't found, no action is taken.
834
835 @param valueToRemove the object to try to remove
836 @see remove, removeRange, removeIf
837 */
838 void removeFirstMatchingValue (ParameterType valueToRemove)
839 {
840 const ScopedLockType lock (getLock());
841 auto* e = values.begin();
842
843 for (int i = 0; i < values.size(); ++i)
844 {
845 if (valueToRemove == e[i])
846 {
847 removeInternal (i);
848 break;
849 }
850 }
851 }
852
853 /** Removes items from the array.
854
855 This will remove all occurrences of the given element from the array.
856 If no such items are found, no action is taken.
857
858 @param valueToRemove the object to try to remove
859 @return how many objects were removed.
860 @see remove, removeRange, removeIf
861 */
862 int removeAllInstancesOf (ParameterType valueToRemove)
863 {
864 int numRemoved = 0;
865 const ScopedLockType lock (getLock());
866
867 for (int i = values.size(); --i >= 0;)
868 {
869 if (valueToRemove == values[i])
870 {
871 removeInternal (i);
872 ++numRemoved;
873 }
874 }
875
876 return numRemoved;
877 }
878
879 /** Removes items from the array.
880
881 This will remove all objects from the array that match a condition.
882 If no such items are found, no action is taken.
883
884 @param predicate the condition when to remove an item. Must be a callable
885 type that takes an ElementType and returns a bool
886
887 @return how many objects were removed.
888 @see remove, removeRange, removeAllInstancesOf
889 */
890 template <typename PredicateType>
891 int removeIf (PredicateType&& predicate)
892 {
893 int numRemoved = 0;
894 const ScopedLockType lock (getLock());
895
896 for (int i = values.size(); --i >= 0;)
897 {
898 if (predicate (values[i]))
899 {
900 removeInternal (i);
901 ++numRemoved;
902 }
903 }
904
905 return numRemoved;
906 }
907
908 /** Removes a range of elements from the array.
909
910 This will remove a set of elements, starting from the given index,
911 and move subsequent elements down to close the gap.
912
913 If the range extends beyond the bounds of the array, it will
914 be safely clipped to the size of the array.
915
916 @param startIndex the index of the first element to remove
917 @param numberToRemove how many elements should be removed
918 @see remove, removeFirstMatchingValue, removeAllInstancesOf, removeIf
919 */
920 void removeRange (int startIndex, int numberToRemove)
921 {
922 const ScopedLockType lock (getLock());
923
924 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
925 startIndex = jlimit (0, values.size(), startIndex);
926 numberToRemove = endIndex - startIndex;
927
928 if (numberToRemove > 0)
929 {
930 values.removeElements (startIndex, numberToRemove);
931 minimiseStorageAfterRemoval();
932 }
933 }
934
935 /** Removes the last n elements from the array.
936
937 @param howManyToRemove how many elements to remove from the end of the array
938 @see remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
939 */
940 void removeLast (int howManyToRemove = 1)
941 {
942 jassert (howManyToRemove >= 0);
943
944 if (howManyToRemove > 0)
945 {
946 const ScopedLockType lock (getLock());
947
948 if (howManyToRemove > values.size())
949 howManyToRemove = values.size();
950
951 values.removeElements (values.size() - howManyToRemove, howManyToRemove);
952 minimiseStorageAfterRemoval();
953 }
954 }
955
956 /** Removes any elements which are also in another array.
957
958 @param otherArray the other array in which to look for elements to remove
959 @see removeValuesNotIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
960 */
961 template <class OtherArrayType>
962 void removeValuesIn (const OtherArrayType& otherArray)
963 {
964 const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
965 const ScopedLockType lock2 (getLock());
966
967 if (this == &otherArray)
968 {
969 clear();
970 }
971 else
972 {
973 if (otherArray.size() > 0)
974 {
975 for (int i = values.size(); --i >= 0;)
976 if (otherArray.contains (values[i]))
977 removeInternal (i);
978 }
979 }
980 }
981
982 /** Removes any elements which are not found in another array.
983
984 Only elements which occur in this other array will be retained.
985
986 @param otherArray the array in which to look for elements NOT to remove
987 @see removeValuesIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
988 */
989 template <class OtherArrayType>
990 void removeValuesNotIn (const OtherArrayType& otherArray)
991 {
992 const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
993 const ScopedLockType lock2 (getLock());
994
995 if (this != &otherArray)
996 {
997 if (otherArray.size() <= 0)
998 {
999 clear();
1000 }
1001 else
1002 {
1003 for (int i = values.size(); --i >= 0;)
1004 if (! otherArray.contains (values[i]))
1005 removeInternal (i);
1006 }
1007 }
1008 }
1009
1010 /** Swaps over two elements in the array.
1011
1012 This swaps over the elements found at the two indexes passed in.
1013 If either index is out-of-range, this method will do nothing.
1014
1015 @param index1 index of one of the elements to swap
1016 @param index2 index of the other element to swap
1017 */
1018 void swap (int index1, int index2)
1019 {
1020 const ScopedLockType lock (getLock());
1021 values.swap (index1, index2);
1022 }
1023
1024 /** Moves one of the values to a different position.
1025
1026 This will move the value to a specified index, shuffling along
1027 any intervening elements as required.
1028
1029 So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
1030 move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
1031
1032 @param currentIndex the index of the value to be moved. If this isn't a
1033 valid index, then nothing will be done
1034 @param newIndex the index at which you'd like this value to end up. If this
1035 is less than zero, the value will be moved to the end
1036 of the array
1037 */
1038 void move (int currentIndex, int newIndex) noexcept
1039 {
1040 if (currentIndex != newIndex)
1041 {
1042 const ScopedLockType lock (getLock());
1043 values.move (currentIndex, newIndex);
1044 }
1045 }
1046
1047 //==============================================================================
1048 /** Reduces the amount of storage being used by the array.
1049
1050 Arrays typically allocate slightly more storage than they need, and after
1051 removing elements, they may have quite a lot of unused space allocated.
1052 This method will reduce the amount of allocated storage to a minimum.
1053 */
1055 {
1056 const ScopedLockType lock (getLock());
1057 values.shrinkToNoMoreThan (values.size());
1058 }
1059
1060 /** Increases the array's internal storage to hold a minimum number of elements.
1061
1062 Calling this before adding a large known number of elements means that
1063 the array won't have to keep dynamically resizing itself as the elements
1064 are added, and it'll therefore be more efficient.
1065 */
1066 void ensureStorageAllocated (int minNumElements)
1067 {
1068 const ScopedLockType lock (getLock());
1069 values.ensureAllocatedSize (minNumElements);
1070 }
1071
1072 //==============================================================================
1073 /** Sorts the array using a default comparison operation.
1074 If the type of your elements isn't supported by the DefaultElementComparator class
1075 then you may need to use the other version of sort, which takes a custom comparator.
1076 */
1077 void sort()
1078 {
1080 sort (comparator);
1081 }
1082
1083 /** Sorts the elements in the array.
1084
1085 This will use a comparator object to sort the elements into order. The object
1086 passed must have a method of the form:
1087 @code
1088 int compareElements (ElementType first, ElementType second);
1089 @endcode
1090
1091 ..and this method must return:
1092 - a value of < 0 if the first comes before the second
1093 - a value of 0 if the two objects are equivalent
1094 - a value of > 0 if the second comes before the first
1095
1096 To improve performance, the compareElements() method can be declared as static or const.
1097
1098 @param comparator the comparator to use for comparing elements.
1099 @param retainOrderOfEquivalentItems if this is true, then items
1100 which the comparator says are equivalent will be
1101 kept in the order in which they currently appear
1102 in the array. This is slower to perform, but may
1103 be important in some cases. If it's false, a faster
1104 algorithm is used, but equivalent elements may be
1105 rearranged.
1106
1107 @see addSorted, indexOfSorted, sortArray
1108 */
1109 template <class ElementComparator>
1110 void sort (ElementComparator& comparator,
1111 bool retainOrderOfEquivalentItems = false)
1112 {
1113 const ScopedLockType lock (getLock());
1114 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
1115 // avoids getting warning messages about the parameter being unused
1116 sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
1117 }
1118
1119 //==============================================================================
1120 /** Returns the CriticalSection that locks this array.
1121 To lock, you can call getLock().enter() and getLock().exit(), or preferably use
1122 an object of ScopedLockType as an RAII lock for it.
1123 */
1124 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
1125
1126 /** Returns the type of scoped lock to use for locking this array */
1127 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
1128
1129
1130 //==============================================================================
1131 #ifndef DOXYGEN
1132 // Note that the swapWithArray method has been replaced by a more flexible templated version,
1133 // and renamed "swapWith" to be more consistent with the names used in other classes.
1134 JUCE_DEPRECATED_WITH_BODY (void swapWithArray (Array& other) noexcept, { swapWith (other); })
1135 #endif
1136
1137private:
1138 //==============================================================================
1140
1141 void removeInternal (int indexToRemove)
1142 {
1143 values.removeElements (indexToRemove, 1);
1144 minimiseStorageAfterRemoval();
1145 }
1146
1147 void minimiseStorageAfterRemoval()
1148 {
1149 if (values.capacity() > jmax (minimumAllocatedSize, values.size() * 2))
1150 values.shrinkToNoMoreThan (jmax (values.size(), jmax (minimumAllocatedSize, 64 / (int) sizeof (ElementType))));
1151 }
1152};
1153
1154} // namespace juce
1155
1156/** @}*/
A basic object container.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:60
int removeIf(PredicateType &&predicate)
Removes items from the array.
Definition: juce_Array.h:891
Array(ElementType &&firstNewElement, OtherElements... otherElements)
Initalises an Array from a list of items.
Definition: juce_Array.h:124
bool operator==(const OtherArrayType &other) const
Compares this array to another one.
Definition: juce_Array.h:166
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
Definition: juce_Array.h:625
void add(ElementType &&newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:432
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
Definition: juce_Array.h:572
bool operator!=(const OtherArrayType &other) const
Compares this array to another one.
Definition: juce_Array.h:179
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
Definition: juce_Array.h:1127
void addNullTerminatedArray(const Type *const *elementsToAdd)
Adds elements from a null-terminated array of pointers to the end of this array.
Definition: juce_Array.h:609
ElementType getUnchecked(int index) const
Returns one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:256
void insertArray(int indexToInsertAt, const ElementType *newElements, int numberOfElements)
Inserts an array of values into this array at a given position.
Definition: juce_Array.h:506
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
Definition: juce_Array.h:226
void removeLast(int howManyToRemove=1)
Removes the last n elements from the array.
Definition: juce_Array.h:940
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
Definition: juce_Array.h:1066
void remove(const ElementType *elementToRemove)
Removes an element from the array.
Definition: juce_Array.h:813
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
Definition: juce_Array.h:1124
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:587
Array(const TypeToCreateFrom *data)
Initalises from a null-terminated raw array of values.
Definition: juce_Array.h:87
void clearQuick()
Removes all elements from the array without freeing the array's allocated storage.
Definition: juce_Array.h:202
void sort()
Sorts the array using a default comparison operation.
Definition: juce_Array.h:1077
int removeAllInstancesOf(ParameterType valueToRemove)
Removes items from the array.
Definition: juce_Array.h:862
Array(const TypeToCreateFrom *data, int numValues)
Initalises from a raw array of values.
Definition: juce_Array.h:98
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
void removeFirstMatchingValue(ParameterType valueToRemove)
Removes an item from the array.
Definition: juce_Array.h:838
void fill(const ParameterType &newValue) noexcept
Fills the Array with the provided value.
Definition: juce_Array.h:209
void removeRange(int startIndex, int numberToRemove)
Removes a range of elements from the array.
Definition: juce_Array.h:920
void removeValuesIn(const OtherArrayType &otherArray)
Removes any elements which are also in another array.
Definition: juce_Array.h:962
const ElementType * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
Definition: juce_Array.h:356
void add(const ElementType &firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition: juce_Array.h:440
void remove(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:771
void insert(int indexToInsertAt, ParameterType newElement)
Inserts a new element into the array at a given position.
Definition: juce_Array.h:466
int indexOfSorted(ElementComparator &comparator, TargetValueType elementToLookFor) const
Finds the index of an element in the array, assuming that the array is sorted.
Definition: juce_Array.h:734
ElementType getFirst() const noexcept
Returns the first element in the array, or a default value if the array is empty.
Definition: juce_Array.h:294
ElementType * begin() noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:332
ElementType * end() noexcept
Returns a pointer to the element which follows the last element in the array.
Definition: juce_Array.h:348
ElementType * getRawDataPointer() noexcept
Returns a pointer to the actual array data.
Definition: juce_Array.h:314
Array(ElementType &&singleElementToAdd)
Initalises an Array of size 1 containing a single element.
Definition: juce_Array.h:110
void addUsingDefaultSort(ParameterType newElement)
Inserts a new element into the array, assuming that the array is sorted.
Definition: juce_Array.h:715
Array()=default
Creates an empty array.
int indexOf(ParameterType elementToLookFor) const
Finds the index of the first element which matches the value passed in.
Definition: juce_Array.h:386
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:422
ElementType removeAndReturn(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:789
Array(const ElementType &firstNewElement, OtherElements... otherElements)
Initalises an Array from a list of items.
Definition: juce_Array.h:117
ElementType operator[](int index) const
Returns one of the elements in the array.
Definition: juce_Array.h:241
Array(const ElementType &singleElementToAdd)
Initalises an Array of size 1 containing a single element.
Definition: juce_Array.h:104
void set(int indexToChange, ParameterType newValue)
Replaces an element with a new value.
Definition: juce_Array.h:546
int addSorted(ElementComparator &comparator, ParameterType newElement)
Inserts a new element into the array, assuming that the array is sorted.
Definition: juce_Array.h:698
bool contains(ParameterType elementToLookFor) const
Returns true if the array contains at least one occurrence of an object.
Definition: juce_Array.h:404
void insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
Inserts multiple copies of an element into the array at a given position.
Definition: juce_Array.h:484
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false)
Sorts the elements in the array.
Definition: juce_Array.h:1110
~Array()=default
Destructor.
const ElementType * data() const noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:372
void resize(int targetNumItems)
This will enlarge or shrink the array to the given number of elements, by adding or removing items fr...
Definition: juce_Array.h:674
void clear()
Removes all elements from the array.
Definition: juce_Array.h:192
void move(int currentIndex, int newIndex) noexcept
Moves one of the values to a different position.
Definition: juce_Array.h:1038
void swap(int index1, int index2)
Swaps over two elements in the array.
Definition: juce_Array.h:1018
ElementType * data() noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:364
void removeValuesNotIn(const OtherArrayType &otherArray)
Removes any elements which are not found in another array.
Definition: juce_Array.h:990
std::enable_if<!std::is_pointer< OtherArrayType >::value, void >::type addArray(const OtherArrayType &arrayToAddFrom, int startIndex, int numElementsToAdd=-1)
Adds elements from another array to the end of this array.
Definition: juce_Array.h:657
const ElementType * begin() const noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:340
const ElementType & getReference(int index) const noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:285
bool addIfNotAlreadyThere(ParameterType newElement)
Appends a new element at the end of the array as long as the array doesn't already contain it.
Definition: juce_Array.h:526
Array(const Array &other)
Creates a copy of another array.
Definition: juce_Array.h:72
void minimiseStorageOverheads()
Reduces the amount of storage being used by the array.
Definition: juce_Array.h:1054
void addArray(const OtherArrayType &arrayToAddFrom)
Adds elements from another array to the end of this array.
Definition: juce_Array.h:638
Array & operator=(const Array &other)
Copies another array.
Definition: juce_Array.h:141
ElementType & getReference(int index) noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:271
ElementType getLast() const noexcept
Returns the last element in the array, or a default value if the array is empty.
Definition: juce_Array.h:304
void add(ElementType &&firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition: juce_Array.h:448
const ElementType * getRawDataPointer() const noexcept
Returns a pointer to the actual array data.
Definition: juce_Array.h:323
A simple ElementComparator class that can be used to sort an array of objects that support the '<' op...