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 
27 namespace 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 */
56 template <typename ElementType,
57  typename TypeOfCriticalSectionToUse = DummyCriticalSection,
58  int minimumAllocatedSize = 0>
59 class Array
60 {
61 private:
62  using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
63 
64 public:
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  */
202  void clearQuick()
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  {
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 
1090 private:
1091  //==============================================================================
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 /** @}*/
void sort()
Sorts the array using a default comparison operation.
Definition: juce_Array.h:1030
ElementType * begin() const noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:309
void removeValuesNotIn(const OtherArrayType &otherArray)
Removes any elements which are not found in another array.
Definition: juce_Array.h:943
int removeIf(PredicateType &&predicate)
Removes items from the array.
Definition: juce_Array.h:844
void removeFirstMatchingValue(ParameterType valueToRemove)
Removes an item from the array.
Definition: juce_Array.h:791
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:540
Array & operator=(const Array &other)
Copies another array.
Definition: juce_Array.h:141
void minimiseStorageOverheads()
Reduces the amount of storage being used by the array.
Definition: juce_Array.h:1007
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
Definition: juce_Array.h:578
void fill(const ParameterType &newValue) noexcept
Fills the Array with the provided value.
Definition: juce_Array.h:209
void clearQuick()
Removes all elements from the array without freeing the array&#39;s allocated storage.
Definition: juce_Array.h:202
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
typename DummyCriticalSection ::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
Definition: juce_Array.h:1080
int indexOf(ParameterType elementToLookFor) const
Finds the index of the first element which matches the value passed in.
Definition: juce_Array.h:339
bool addIfNotAlreadyThere(ParameterType newElement)
Appends a new element at the end of the array as long as the array doesn&#39;t already contain it...
Definition: juce_Array.h:479
Array(const ElementType &firstNewElement, OtherElements... otherElements)
Initalises an Array from a list of items.
Definition: juce_Array.h:117
void removeValuesIn(const OtherArrayType &otherArray)
Removes any elements which are also in another array.
Definition: juce_Array.h:915
void ensureStorageAllocated(int minNumElements)
Increases the array&#39;s internal storage to hold a minimum number of elements.
Definition: juce_Array.h:1019
void swap(int index1, int index2)
Swaps over two elements in the array.
Definition: juce_Array.h:971
void add(ElementType &&newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:385
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:375
void add(const ElementType &firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition: juce_Array.h:393
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 addArray(const OtherArrayType &arrayToAddFrom)
Adds elements from another array to the end of this array.
Definition: juce_Array.h:591
void move(int currentIndex, int newIndex) noexcept
Moves one of the values to a different position.
Definition: juce_Array.h:991
Array(const TypeToCreateFrom *data)
Initalises from a null-terminated raw array of values.
Definition: juce_Array.h:87
Array(const ElementType &singleElementToAdd)
Initalises an Array of size 1 containing a single element.
Definition: juce_Array.h:104
ElementType operator[](int index) const
Returns one of the elements in the array.
Definition: juce_Array.h:241
A basic object container.
Array(const TypeToCreateFrom *data, int numValues)
Initalises from a raw array of values.
Definition: juce_Array.h:98
void insert(int indexToInsertAt, ParameterType newElement)
Inserts a new element into the array at a given position.
Definition: juce_Array.h:419
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
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 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
int addSorted(ElementComparator &comparator, ParameterType newElement)
Inserts a new element into the array, assuming that the array is sorted.
Definition: juce_Array.h:651
Array(const Array &other)
Creates a copy of another array.
Definition: juce_Array.h:72
Array(ElementType &&singleElementToAdd)
Initalises an Array of size 1 containing a single element.
Definition: juce_Array.h:110
bool operator!=(const OtherArrayType &other) const
Compares this array to another one.
Definition: juce_Array.h:179
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
Array()=default
Creates an empty array.
void add(ElementType &&firstNewElement, OtherElements... otherElements)
Appends multiple new elements at the end of the array.
Definition: juce_Array.h:401
void removeLast(int howManyToRemove=1)
Removes the last n elements from the array.
Definition: juce_Array.h:893
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
Definition: juce_Array.h:525
ElementType * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
Definition: juce_Array.h:317
ElementType * data() const noexcept
Returns a pointer to the first element in the array.
Definition: juce_Array.h:325
void addUsingDefaultSort(ParameterType newElement)
Inserts a new element into the array, assuming that the array is sorted.
Definition: juce_Array.h:668
A simple ElementComparator class that can be used to sort an array of objects that support the &#39;<&#39; op...
~Array()=default
Destructor.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
void clear()
Removes all elements from the array.
Definition: juce_Array.h:192
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
ElementType removeAndReturn(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:742
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
Definition: juce_Array.h:1077
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
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
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
Definition: juce_Array.h:226
Array(ElementType &&firstNewElement, OtherElements... otherElements)
Initalises an Array from a list of items.
Definition: juce_Array.h:124
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
int removeAllInstancesOf(ParameterType valueToRemove)
Removes items from the array.
Definition: juce_Array.h:815
bool contains(ParameterType elementToLookFor) const
Returns true if the array contains at least one occurrence of an object.
Definition: juce_Array.h:357
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
void removeRange(int startIndex, int numberToRemove)
Removes a range of elements from the array.
Definition: juce_Array.h:873
bool operator==(const OtherArrayType &other) const
Compares this array to another one.
Definition: juce_Array.h:166
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false)
Sorts the elements in the array.
Definition: juce_Array.h:1063