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