OpenShot Library | libopenshot-audio 0.2.0
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 fulfil 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) const noexcept
272 {
273 const ScopedLockType lock (getLock());
274 return values[index];
275 }
276
277 /** Returns the first element in the array, or a default value if the array is empty.
278 @see operator[], getUnchecked, getLast
279 */
280 inline ElementType getFirst() const noexcept
281 {
282 const ScopedLockType lock (getLock());
283 return values.getFirst();
284 }
285
286 /** Returns the last element in the array, or a default value if the array is empty.
287
288 @see operator[], getUnchecked, getFirst
289 */
290 inline ElementType getLast() const noexcept
291 {
292 const ScopedLockType lock (getLock());
293 return values.getLast();
294 }
295
296 /** Returns a pointer to the actual array data.
297 This pointer will only be valid until the next time a non-const method
298 is called on the array.
299 */
300 inline ElementType* getRawDataPointer() noexcept
301 {
302 return values.begin();
303 }
304
305 //==============================================================================
306 /** Returns a pointer to the first element in the array.
307 This method is provided for compatibility with standard C++ iteration mechanisms.
308 */
309 inline ElementType* begin() const noexcept
310 {
311 return values.begin();
312 }
313
314 /** Returns a pointer to the element which follows the last element in the array.
315 This method is provided for compatibility with standard C++ iteration mechanisms.
316 */
317 inline ElementType* end() const noexcept
318 {
319 return values.end();
320 }
321
322 /** Returns a pointer to the first element in the array.
323 This method is provided for compatibility with the standard C++ containers.
324 */
325 inline ElementType* data() const noexcept
326 {
327 return begin();
328 }
329
330 //==============================================================================
331 /** Finds the index of the first element which matches the value passed in.
332
333 This will search the array for the given object, and return the index
334 of its first occurrence. If the object isn't found, the method will return -1.
335
336 @param elementToLookFor the value or object to look for
337 @returns the index of the object, or -1 if it's not found
338 */
339 int indexOf (ParameterType elementToLookFor) const
340 {
341 const ScopedLockType lock (getLock());
342 auto e = values.begin();
343 auto endPtr = values.end();
344
345 for (; e != endPtr; ++e)
346 if (elementToLookFor == *e)
347 return static_cast<int> (e - values.begin());
348
349 return -1;
350 }
351
352 /** Returns true if the array contains at least one occurrence of an object.
353
354 @param elementToLookFor the value or object to look for
355 @returns true if the item is found
356 */
357 bool contains (ParameterType elementToLookFor) const
358 {
359 const ScopedLockType lock (getLock());
360 auto e = values.begin();
361 auto endPtr = values.end();
362
363 for (; e != endPtr; ++e)
364 if (elementToLookFor == *e)
365 return true;
366
367 return false;
368 }
369
370 //==============================================================================
371 /** Appends a new element at the end of the array.
372 @param newElement the new object to add to the array
373 @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
374 */
375 void add (const ElementType& newElement)
376 {
377 const ScopedLockType lock (getLock());
378 values.add (newElement);
379 }
380
381 /** Appends a new element at the end of the array.
382 @param newElement the new object to add to the array
383 @see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
384 */
385 void add (ElementType&& newElement)
386 {
387 const ScopedLockType lock (getLock());
388 values.add (std::move (newElement));
389 }
390
391 /** Appends multiple new elements at the end of the array. */
392 template <typename... OtherElements>
393 void add (const ElementType& firstNewElement, OtherElements... otherElements)
394 {
395 const ScopedLockType lock (getLock());
396 values.add (firstNewElement, otherElements...);
397 }
398
399 /** Appends multiple new elements at the end of the array. */
400 template <typename... OtherElements>
401 void add (ElementType&& firstNewElement, OtherElements... otherElements)
402 {
403 const ScopedLockType lock (getLock());
404 values.add (std::move (firstNewElement), otherElements...);
405 }
406
407 /** Inserts a new element into the array at a given position.
408
409 If the index is less than 0 or greater than the size of the array, the
410 element will be added to the end of the array.
411 Otherwise, it will be inserted into the array, moving all the later elements
412 along to make room.
413
414 @param indexToInsertAt the index at which the new element should be
415 inserted (pass in -1 to add it to the end)
416 @param newElement the new object to add to the array
417 @see add, addSorted, addUsingDefaultSort, set
418 */
419 void insert (int indexToInsertAt, ParameterType newElement)
420 {
421 const ScopedLockType lock (getLock());
422 values.insert (indexToInsertAt, newElement, 1);
423 }
424
425 /** Inserts multiple copies of an element into the array at a given position.
426
427 If the index is less than 0 or greater than the size of the array, the
428 element will be added to the end of the array.
429 Otherwise, it will be inserted into the array, moving all the later elements
430 along to make room.
431
432 @param indexToInsertAt the index at which the new element should be inserted
433 @param newElement the new object to add to the array
434 @param numberOfTimesToInsertIt how many copies of the value to insert
435 @see insert, add, addSorted, set
436 */
437 void insertMultiple (int indexToInsertAt, ParameterType newElement,
438 int numberOfTimesToInsertIt)
439 {
440 if (numberOfTimesToInsertIt > 0)
441 {
442 const ScopedLockType lock (getLock());
443 values.insert (indexToInsertAt, newElement, numberOfTimesToInsertIt);
444 }
445 }
446
447 /** Inserts an array of values into this array at a given position.
448
449 If the index is less than 0 or greater than the size of the array, the
450 new elements will be added to the end of the array.
451 Otherwise, they will be inserted into the array, moving all the later elements
452 along to make room.
453
454 @param indexToInsertAt the index at which the first new element should be inserted
455 @param newElements the new values to add to the array
456 @param numberOfElements how many items are in the array
457 @see insert, add, addSorted, set
458 */
459 void insertArray (int indexToInsertAt,
460 const ElementType* newElements,
461 int numberOfElements)
462 {
463 if (numberOfElements > 0)
464 {
465 const ScopedLockType lock (getLock());
466 values.insertArray (indexToInsertAt, newElements, numberOfElements);
467 }
468 }
469
470 /** Appends a new element at the end of the array as long as the array doesn't
471 already contain it.
472
473 If the array already contains an element that matches the one passed in, nothing
474 will be done.
475
476 @param newElement the new object to add to the array
477 @return true if the element was added to the array; false otherwise.
478 */
479 bool addIfNotAlreadyThere (ParameterType newElement)
480 {
481 const ScopedLockType lock (getLock());
482
483 if (contains (newElement))
484 return false;
485
486 add (newElement);
487 return true;
488 }
489
490 /** Replaces an element with a new value.
491
492 If the index is less than zero, this method does nothing.
493 If the index is beyond the end of the array, the item is added to the end of the array.
494
495 @param indexToChange the index whose value you want to change
496 @param newValue the new value to set for this index.
497 @see add, insert
498 */
499 void set (int indexToChange, ParameterType newValue)
500 {
501 if (indexToChange >= 0)
502 {
503 const ScopedLockType lock (getLock());
504
505 if (indexToChange < values.size())
506 values[indexToChange] = newValue;
507 else
508 values.add (newValue);
509 }
510 else
511 {
512 jassertfalse;
513 }
514 }
515
516 /** Replaces an element with a new value without doing any bounds-checking.
517
518 This just sets a value directly in the array's internal storage, so you'd
519 better make sure it's in range!
520
521 @param indexToChange the index whose value you want to change
522 @param newValue the new value to set for this index.
523 @see set, getUnchecked
524 */
525 void setUnchecked (int indexToChange, ParameterType newValue)
526 {
527 const ScopedLockType lock (getLock());
528 jassert (isPositiveAndBelow (indexToChange, values.size()));
529 values[indexToChange] = newValue;
530 }
531
532 /** Adds elements from an array to the end of this array.
533
534 @param elementsToAdd an array of some kind of object from which elements
535 can be constructed.
536 @param numElementsToAdd how many elements are in this other array
537 @see add
538 */
539 template <typename Type>
540 void addArray (const Type* elementsToAdd, int numElementsToAdd)
541 {
542 const ScopedLockType lock (getLock());
543
544 if (numElementsToAdd > 0)
545 values.addArray (elementsToAdd, numElementsToAdd);
546 }
547
548 template <typename TypeToCreateFrom>
549 void addArray (const std::initializer_list<TypeToCreateFrom>& items)
550 {
551 const ScopedLockType lock (getLock());
552 values.addArray (items);
553 }
554
555 /** Adds elements from a null-terminated array of pointers to the end of this array.
556
557 @param elementsToAdd an array of pointers to some kind of object from which elements
558 can be constructed. This array must be terminated by a nullptr
559 @see addArray
560 */
561 template <typename Type>
562 void addNullTerminatedArray (const Type* const* elementsToAdd)
563 {
564 int num = 0;
565
566 for (auto e = elementsToAdd; *e != nullptr; ++e)
567 ++num;
568
569 addArray (elementsToAdd, num);
570 }
571
572 /** This swaps the contents of this array with those of another array.
573
574 If you need to exchange two arrays, this is vastly quicker than using copy-by-value
575 because it just swaps their internal pointers.
576 */
577 template <class OtherArrayType>
578 void swapWith (OtherArrayType& otherArray) noexcept
579 {
580 const ScopedLockType lock1 (getLock());
581 const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
582 values.swapWith (otherArray.values);
583 }
584
585 /** Adds elements from another array to the end of this array.
586
587 @param arrayToAddFrom the array from which to copy the elements
588 @see add
589 */
590 template <class OtherArrayType>
591 void addArray (const OtherArrayType& arrayToAddFrom)
592 {
593 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
594 const ScopedLockType lock2 (getLock());
595
596 values.addArray (arrayToAddFrom);
597 }
598
599 /** Adds elements from another array to the end of this array.
600
601 @param arrayToAddFrom the array from which to copy the elements
602 @param startIndex the first element of the other array to start copying from
603 @param numElementsToAdd how many elements to add from the other array. If this
604 value is negative or greater than the number of available elements,
605 all available elements will be copied.
606 @see add
607 */
608 template <class OtherArrayType>
609 typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type
610 addArray (const OtherArrayType& arrayToAddFrom,
611 int startIndex,
612 int numElementsToAdd = -1)
613 {
614 const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
615 const ScopedLockType lock2 (getLock());
616
617 values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
618 }
619
620 /** This will enlarge or shrink the array to the given number of elements, by adding
621 or removing items from its end.
622
623 If the array is smaller than the given target size, empty elements will be appended
624 until its size is as specified. If its size is larger than the target, items will be
625 removed from its end to shorten it.
626 */
627 void resize (int targetNumItems)
628 {
629 jassert (targetNumItems >= 0);
630 auto numToAdd = targetNumItems - values.size();
631
632 if (numToAdd > 0)
633 insertMultiple (values.size(), ElementType(), numToAdd);
634 else if (numToAdd < 0)
635 removeRange (targetNumItems, -numToAdd);
636 }
637
638 /** Inserts a new element into the array, assuming that the array is sorted.
639
640 This will use a comparator to find the position at which the new element
641 should go. If the array isn't sorted, the behaviour of this
642 method will be unpredictable.
643
644 @param comparator the comparator to use to compare the elements - see the sort()
645 method for details about the form this object should take
646 @param newElement the new element to insert to the array
647 @returns the index at which the new item was added
648 @see addUsingDefaultSort, add, sort
649 */
650 template <class ElementComparator>
651 int addSorted (ElementComparator& comparator, ParameterType newElement)
652 {
653 const ScopedLockType lock (getLock());
654 auto index = findInsertIndexInSortedArray (comparator, values.begin(), newElement, 0, values.size());
655 insert (index, newElement);
656 return index;
657 }
658
659 /** Inserts a new element into the array, assuming that the array is sorted.
660
661 This will use the DefaultElementComparator class for sorting, so your ElementType
662 must be suitable for use with that class. If the array isn't sorted, the behaviour of this
663 method will be unpredictable.
664
665 @param newElement the new element to insert to the array
666 @see addSorted, sort
667 */
668 void addUsingDefaultSort (ParameterType newElement)
669 {
670 DefaultElementComparator <ElementType> comparator;
671 addSorted (comparator, newElement);
672 }
673
674 /** Finds the index of an element in the array, assuming that the array is sorted.
675
676 This will use a comparator to do a binary-chop to find the index of the given
677 element, if it exists. If the array isn't sorted, the behaviour of this
678 method will be unpredictable.
679
680 @param comparator the comparator to use to compare the elements - see the sort()
681 method for details about the form this object should take
682 @param elementToLookFor the element to search for
683 @returns the index of the element, or -1 if it's not found
684 @see addSorted, sort
685 */
686 template <typename ElementComparator, typename TargetValueType>
687 int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const
688 {
689 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
690 // avoids getting warning messages about the parameter being unused
691
692 const ScopedLockType lock (getLock());
693
694 for (int s = 0, e = values.size();;)
695 {
696 if (s >= e)
697 return -1;
698
699 if (comparator.compareElements (elementToLookFor, values[s]) == 0)
700 return s;
701
702 auto halfway = (s + e) / 2;
703
704 if (halfway == s)
705 return -1;
706
707 if (comparator.compareElements (elementToLookFor, values[halfway]) >= 0)
708 s = halfway;
709 else
710 e = halfway;
711 }
712 }
713
714 //==============================================================================
715 /** Removes an element from the array.
716
717 This will remove the element at a given index, and move back
718 all the subsequent elements to close the gap.
719 If the index passed in is out-of-range, nothing will happen.
720
721 @param indexToRemove the index of the element to remove
722 @see removeAndReturn, removeFirstMatchingValue, removeAllInstancesOf, removeRange
723 */
724 void remove (int indexToRemove)
725 {
726 const ScopedLockType lock (getLock());
727
728 if (isPositiveAndBelow (indexToRemove, values.size()))
729 removeInternal (indexToRemove);
730 }
731
732 /** Removes an element from the array.
733
734 This will remove the element at a given index, and move back
735 all the subsequent elements to close the gap.
736 If the index passed in is out-of-range, nothing will happen.
737
738 @param indexToRemove the index of the element to remove
739 @returns the element that has been removed
740 @see removeFirstMatchingValue, removeAllInstancesOf, removeRange
741 */
742 ElementType removeAndReturn (int indexToRemove)
743 {
744 const ScopedLockType lock (getLock());
745
746 if (isPositiveAndBelow (indexToRemove, values.size()))
747 {
748 ElementType removed (values[indexToRemove]);
749 removeInternal (indexToRemove);
750 return removed;
751 }
752
753 return ElementType();
754 }
755
756 /** Removes an element from the array.
757
758 This will remove the element pointed to by the given iterator,
759 and move back all the subsequent elements to close the gap.
760 If the iterator passed in does not point to an element within the
761 array, behaviour is undefined.
762
763 @param elementToRemove a pointer to the element to remove
764 @see removeFirstMatchingValue, removeAllInstancesOf, removeRange, removeIf
765 */
766 void remove (const ElementType* elementToRemove)
767 {
768 jassert (elementToRemove != nullptr);
769 const ScopedLockType lock (getLock());
770
771 jassert (values.begin() != nullptr);
772 auto indexToRemove = (int) (elementToRemove - values.begin());
773
774 if (! isPositiveAndBelow (indexToRemove, values.size()))
775 {
776 jassertfalse;
777 return;
778 }
779
780 removeInternal (indexToRemove);
781 }
782
783 /** Removes an item from the array.
784
785 This will remove the first occurrence of the given element from the array.
786 If the item isn't found, no action is taken.
787
788 @param valueToRemove the object to try to remove
789 @see remove, removeRange, removeIf
790 */
791 void removeFirstMatchingValue (ParameterType valueToRemove)
792 {
793 const ScopedLockType lock (getLock());
794 auto* e = values.begin();
795
796 for (int i = 0; i < values.size(); ++i)
797 {
798 if (valueToRemove == e[i])
799 {
800 removeInternal (i);
801 break;
802 }
803 }
804 }
805
806 /** Removes items from the array.
807
808 This will remove all occurrences of the given element from the array.
809 If no such items are found, no action is taken.
810
811 @param valueToRemove the object to try to remove
812 @return how many objects were removed.
813 @see remove, removeRange, removeIf
814 */
815 int removeAllInstancesOf (ParameterType valueToRemove)
816 {
817 int numRemoved = 0;
818 const ScopedLockType lock (getLock());
819
820 for (int i = values.size(); --i >= 0;)
821 {
822 if (valueToRemove == values[i])
823 {
824 removeInternal (i);
825 ++numRemoved;
826 }
827 }
828
829 return numRemoved;
830 }
831
832 /** Removes items from the array.
833
834 This will remove all objects from the array that match a condition.
835 If no such items are found, no action is taken.
836
837 @param predicate the condition when to remove an item. Must be a callable
838 type that takes an ElementType and returns a bool
839
840 @return how many objects were removed.
841 @see remove, removeRange, removeAllInstancesOf
842 */
843 template <typename PredicateType>
844 int removeIf (PredicateType&& predicate)
845 {
846 int numRemoved = 0;
847 const ScopedLockType lock (getLock());
848
849 for (int i = values.size(); --i >= 0;)
850 {
851 if (predicate (values[i]))
852 {
853 removeInternal (i);
854 ++numRemoved;
855 }
856 }
857
858 return numRemoved;
859 }
860
861 /** Removes a range of elements from the array.
862
863 This will remove a set of elements, starting from the given index,
864 and move subsequent elements down to close the gap.
865
866 If the range extends beyond the bounds of the array, it will
867 be safely clipped to the size of the array.
868
869 @param startIndex the index of the first element to remove
870 @param numberToRemove how many elements should be removed
871 @see remove, removeFirstMatchingValue, removeAllInstancesOf, removeIf
872 */
873 void removeRange (int startIndex, int numberToRemove)
874 {
875 const ScopedLockType lock (getLock());
876
877 auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
878 startIndex = jlimit (0, values.size(), startIndex);
879 numberToRemove = endIndex - startIndex;
880
881 if (numberToRemove > 0)
882 {
883 values.removeElements (startIndex, numberToRemove);
884 minimiseStorageAfterRemoval();
885 }
886 }
887
888 /** Removes the last n elements from the array.
889
890 @param howManyToRemove how many elements to remove from the end of the array
891 @see remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
892 */
893 void removeLast (int howManyToRemove = 1)
894 {
895 jassert (howManyToRemove >= 0);
896
897 if (howManyToRemove > 0)
898 {
899 const ScopedLockType lock (getLock());
900
901 if (howManyToRemove > values.size())
902 howManyToRemove = values.size();
903
904 values.removeElements (values.size() - howManyToRemove, howManyToRemove);
905 minimiseStorageAfterRemoval();
906 }
907 }
908
909 /** Removes any elements which are also in another array.
910
911 @param otherArray the other array in which to look for elements to remove
912 @see removeValuesNotIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
913 */
914 template <class OtherArrayType>
915 void removeValuesIn (const OtherArrayType& otherArray)
916 {
917 const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
918 const ScopedLockType lock2 (getLock());
919
920 if (this == &otherArray)
921 {
922 clear();
923 }
924 else
925 {
926 if (otherArray.size() > 0)
927 {
928 for (int i = values.size(); --i >= 0;)
929 if (otherArray.contains (values[i]))
930 removeInternal (i);
931 }
932 }
933 }
934
935 /** Removes any elements which are not found in another array.
936
937 Only elements which occur in this other array will be retained.
938
939 @param otherArray the array in which to look for elements NOT to remove
940 @see removeValuesIn, remove, removeFirstMatchingValue, removeAllInstancesOf, removeRange
941 */
942 template <class OtherArrayType>
943 void removeValuesNotIn (const OtherArrayType& otherArray)
944 {
945 const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
946 const ScopedLockType lock2 (getLock());
947
948 if (this != &otherArray)
949 {
950 if (otherArray.size() <= 0)
951 {
952 clear();
953 }
954 else
955 {
956 for (int i = values.size(); --i >= 0;)
957 if (! otherArray.contains (values[i]))
958 removeInternal (i);
959 }
960 }
961 }
962
963 /** Swaps over two elements in the array.
964
965 This swaps over the elements found at the two indexes passed in.
966 If either index is out-of-range, this method will do nothing.
967
968 @param index1 index of one of the elements to swap
969 @param index2 index of the other element to swap
970 */
971 void swap (int index1, int index2)
972 {
973 const ScopedLockType lock (getLock());
974 values.swap (index1, index2);
975 }
976
977 /** Moves one of the values to a different position.
978
979 This will move the value to a specified index, shuffling along
980 any intervening elements as required.
981
982 So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
983 move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
984
985 @param currentIndex the index of the value to be moved. If this isn't a
986 valid index, then nothing will be done
987 @param newIndex the index at which you'd like this value to end up. If this
988 is less than zero, the value will be moved to the end
989 of the array
990 */
991 void move (int currentIndex, int newIndex) noexcept
992 {
993 if (currentIndex != newIndex)
994 {
995 const ScopedLockType lock (getLock());
996 values.move (currentIndex, newIndex);
997 }
998 }
999
1000 //==============================================================================
1001 /** Reduces the amount of storage being used by the array.
1002
1003 Arrays typically allocate slightly more storage than they need, and after
1004 removing elements, they may have quite a lot of unused space allocated.
1005 This method will reduce the amount of allocated storage to a minimum.
1006 */
1008 {
1009 const ScopedLockType lock (getLock());
1010 values.shrinkToNoMoreThan (values.size());
1011 }
1012
1013 /** Increases the array's internal storage to hold a minimum number of elements.
1014
1015 Calling this before adding a large known number of elements means that
1016 the array won't have to keep dynamically resizing itself as the elements
1017 are added, and it'll therefore be more efficient.
1018 */
1019 void ensureStorageAllocated (int minNumElements)
1020 {
1021 const ScopedLockType lock (getLock());
1022 values.ensureAllocatedSize (minNumElements);
1023 }
1024
1025 //==============================================================================
1026 /** Sorts the array using a default comparison operation.
1027 If the type of your elements isn't supported by the DefaultElementComparator class
1028 then you may need to use the other version of sort, which takes a custom comparator.
1029 */
1030 void sort()
1031 {
1033 sort (comparator);
1034 }
1035
1036 /** Sorts the elements in the array.
1037
1038 This will use a comparator object to sort the elements into order. The object
1039 passed must have a method of the form:
1040 @code
1041 int compareElements (ElementType first, ElementType second);
1042 @endcode
1043
1044 ..and this method must return:
1045 - a value of < 0 if the first comes before the second
1046 - a value of 0 if the two objects are equivalent
1047 - a value of > 0 if the second comes before the first
1048
1049 To improve performance, the compareElements() method can be declared as static or const.
1050
1051 @param comparator the comparator to use for comparing elements.
1052 @param retainOrderOfEquivalentItems if this is true, then items
1053 which the comparator says are equivalent will be
1054 kept in the order in which they currently appear
1055 in the array. This is slower to perform, but may
1056 be important in some cases. If it's false, a faster
1057 algorithm is used, but equivalent elements may be
1058 rearranged.
1059
1060 @see addSorted, indexOfSorted, sortArray
1061 */
1062 template <class ElementComparator>
1063 void sort (ElementComparator& comparator,
1064 bool retainOrderOfEquivalentItems = false)
1065 {
1066 const ScopedLockType lock (getLock());
1067 ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
1068 // avoids getting warning messages about the parameter being unused
1069 sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
1070 }
1071
1072 //==============================================================================
1073 /** Returns the CriticalSection that locks this array.
1074 To lock, you can call getLock().enter() and getLock().exit(), or preferably use
1075 an object of ScopedLockType as an RAII lock for it.
1076 */
1077 inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
1078
1079 /** Returns the type of scoped lock to use for locking this array */
1080 using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
1081
1082
1083 //==============================================================================
1084 #ifndef DOXYGEN
1085 // Note that the swapWithArray method has been replaced by a more flexible templated version,
1086 // and renamed "swapWith" to be more consistent with the names used in other classes.
1087 JUCE_DEPRECATED_WITH_BODY (void swapWithArray (Array& other) noexcept, { swapWith (other); })
1088 #endif
1089
1090private:
1091 //==============================================================================
1092 ArrayBase<ElementType, TypeOfCriticalSectionToUse> values;
1093
1094 void removeInternal (int indexToRemove)
1095 {
1096 values.removeElements (indexToRemove, 1);
1097 minimiseStorageAfterRemoval();
1098 }
1099
1100 void minimiseStorageAfterRemoval()
1101 {
1102 if (values.capacity() > jmax (minimumAllocatedSize, values.size() * 2))
1103 values.shrinkToNoMoreThan (jmax (values.size(), jmax (minimumAllocatedSize, 64 / (int) sizeof (ElementType))));
1104 }
1105};
1106
1107} // namespace juce
1108
1109/** @}*/
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:844
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:578
void add(ElementType &&newElement)
Appends a new element at the end of the array.
Definition juce_Array.h:385
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
Definition juce_Array.h:525
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.
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:562
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:459
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:893
void ensureStorageAllocated(int minNumElements)
Increases the array's internal storage to hold a minimum number of elements.
void remove(const ElementType *elementToRemove)
Removes an element from the array.
Definition juce_Array.h:766
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition juce_Array.h:540
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.
int removeAllInstancesOf(ParameterType valueToRemove)
Removes items from the array.
Definition juce_Array.h:815
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:791
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:873
void removeValuesIn(const OtherArrayType &otherArray)
Removes any elements which are also in another array.
Definition juce_Array.h:915
ElementType * begin() const noexcept
Returns a pointer to the first element in the array.
Definition juce_Array.h:309
void add(const ElementType &firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition juce_Array.h:393
void remove(int indexToRemove)
Removes an element from the array.
Definition juce_Array.h:724
void insert(int indexToInsertAt, ParameterType newElement)
Inserts a new element into the array at a given position.
Definition juce_Array.h:419
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:687
ElementType getFirst() const noexcept
Returns the first element in the array, or a default value if the array is empty.
Definition juce_Array.h:280
ElementType * getRawDataPointer() noexcept
Returns a pointer to the actual array data.
Definition juce_Array.h:300
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:668
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:339
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition juce_Array.h:375
ElementType removeAndReturn(int indexToRemove)
Removes an element from the array.
Definition juce_Array.h:742
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
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:271
void set(int indexToChange, ParameterType newValue)
Replaces an element with a new value.
Definition juce_Array.h:499
int addSorted(ElementComparator &comparator, ParameterType newElement)
Inserts a new element into the array, assuming that the array is sorted.
Definition juce_Array.h:651
bool contains(ParameterType elementToLookFor) const
Returns true if the array contains at least one occurrence of an object.
Definition juce_Array.h:357
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:437
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false)
Sorts the elements in the array.
~Array()=default
Destructor.
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:627
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:991
void swap(int index1, int index2)
Swaps over two elements in the array.
Definition juce_Array.h:971
void removeValuesNotIn(const OtherArrayType &otherArray)
Removes any elements which are not found in another array.
Definition juce_Array.h:943
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:610
ElementType * data() const noexcept
Returns a pointer to the first element in the array.
Definition juce_Array.h:325
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:479
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.
void addArray(const OtherArrayType &arrayToAddFrom)
Adds elements from another array to the end of this array.
Definition juce_Array.h:591
Array & operator=(const Array &other)
Copies another array.
Definition juce_Array.h:141
ElementType getLast() const noexcept
Returns the last element in the array, or a default value if the array is empty.
Definition juce_Array.h:290
void add(ElementType &&firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition juce_Array.h:401
ElementType * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
Definition juce_Array.h:317
A simple ElementComparator class that can be used to sort an array of objects that support the '<' op...