OpenShot Audio Library | OpenShotAudio  0.3.1
juce_Array.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
52 template <typename ElementType,
53  typename TypeOfCriticalSectionToUse = DummyCriticalSection,
54  int minimumAllocatedSize = 0>
55 class Array
56 {
57 private:
58  using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
59 
60 public:
61  //==============================================================================
63  Array() = default;
64 
68  Array (const Array& other)
69  {
70  const ScopedLockType lock (other.getLock());
71  values.addArray (other.values.begin(), other.values.size());
72  }
73 
74  Array (Array&& other) noexcept
75  : values (std::move (other.values))
76  {
77  }
78 
82  template <typename TypeToCreateFrom>
83  explicit Array (const TypeToCreateFrom* data)
84  {
85  while (*values != TypeToCreateFrom())
86  add (*data++);
87  }
88 
93  template <typename TypeToCreateFrom>
94  Array (const TypeToCreateFrom* data, int numValues)
95  {
96  values.addArray (data, numValues);
97  }
98 
100  Array (const ElementType& singleElementToAdd)
101  {
102  add (singleElementToAdd);
103  }
104 
106  Array (ElementType&& singleElementToAdd)
107  {
108  add (std::move (singleElementToAdd));
109  }
110 
112  template <typename... OtherElements>
113  Array (const ElementType& firstNewElement, OtherElements... otherElements)
114  {
115  values.add (firstNewElement, otherElements...);
116  }
117 
119  template <typename... OtherElements>
120  Array (ElementType&& firstNewElement, OtherElements... otherElements)
121  {
122  values.add (std::move (firstNewElement), otherElements...);
123  }
124 
125  template <typename TypeToCreateFrom>
126  Array (const std::initializer_list<TypeToCreateFrom>& items)
127  {
128  addArray (items);
129  }
130 
132  ~Array() = default;
133 
137  Array& operator= (const Array& other)
138  {
139  if (this != &other)
140  {
141  auto otherCopy (other);
142  swapWith (otherCopy);
143  }
144 
145  return *this;
146  }
147 
148  Array& operator= (Array&& other) noexcept
149  {
150  const ScopedLockType lock (getLock());
151  values = std::move (other.values);
152  return *this;
153  }
154 
155  //==============================================================================
161  template <class OtherArrayType>
162  bool operator== (const OtherArrayType& other) const
163  {
164  const ScopedLockType lock (getLock());
165  const typename OtherArrayType::ScopedLockType lock2 (other.getLock());
166  return values == other;
167  }
168 
174  template <class OtherArrayType>
175  bool operator!= (const OtherArrayType& other) const
176  {
177  return ! operator== (other);
178  }
179 
180  //==============================================================================
188  void clear()
189  {
190  const ScopedLockType lock (getLock());
191  clearQuick();
192  values.setAllocatedSize (0);
193  }
194 
198  void clearQuick()
199  {
200  const ScopedLockType lock (getLock());
201  values.clear();
202  }
203 
205  void fill (const ParameterType& newValue) noexcept
206  {
207  const ScopedLockType lock (getLock());
208 
209  for (auto& e : *this)
210  e = newValue;
211  }
212 
213  //==============================================================================
215  inline int size() const noexcept
216  {
217  const ScopedLockType lock (getLock());
218  return values.size();
219  }
220 
222  inline bool isEmpty() const noexcept
223  {
224  return size() == 0;
225  }
226 
237  ElementType operator[] (int index) const
238  {
239  const ScopedLockType lock (getLock());
240  return values.getValueWithDefault (index);
241  }
242 
252  inline ElementType getUnchecked (int index) const
253  {
254  const ScopedLockType lock (getLock());
255  return values[index];
256  }
257 
267  inline ElementType& getReference (int index) noexcept
268  {
269  const ScopedLockType lock (getLock());
270  return values[index];
271  }
272 
281  inline const ElementType& getReference (int index) const noexcept
282  {
283  const ScopedLockType lock (getLock());
284  return values[index];
285  }
286 
290  inline ElementType getFirst() const noexcept
291  {
292  const ScopedLockType lock (getLock());
293  return values.getFirst();
294  }
295 
300  inline ElementType getLast() const noexcept
301  {
302  const ScopedLockType lock (getLock());
303  return values.getLast();
304  }
305 
310  inline ElementType* getRawDataPointer() noexcept
311  {
312  return values.begin();
313  }
314 
319  inline const ElementType* getRawDataPointer() const noexcept
320  {
321  return values.begin();
322  }
323 
324  //==============================================================================
328  inline ElementType* begin() noexcept
329  {
330  return values.begin();
331  }
332 
336  inline const ElementType* begin() const noexcept
337  {
338  return values.begin();
339  }
340 
344  inline ElementType* end() noexcept
345  {
346  return values.end();
347  }
348 
352  inline const ElementType* end() const noexcept
353  {
354  return values.end();
355  }
356 
360  inline ElementType* data() noexcept
361  {
362  return begin();
363  }
364 
368  inline const ElementType* data() const noexcept
369  {
370  return begin();
371  }
372 
373  //==============================================================================
382  int indexOf (ParameterType elementToLookFor) const
383  {
384  const ScopedLockType lock (getLock());
385  auto e = values.begin();
386  auto endPtr = values.end();
387 
388  for (; e != endPtr; ++e)
389  if (elementToLookFor == *e)
390  return static_cast<int> (e - values.begin());
391 
392  return -1;
393  }
394 
400  bool contains (ParameterType elementToLookFor) const
401  {
402  const ScopedLockType lock (getLock());
403  auto e = values.begin();
404  auto endPtr = values.end();
405 
406  for (; e != endPtr; ++e)
407  if (elementToLookFor == *e)
408  return true;
409 
410  return false;
411  }
412 
413  //==============================================================================
418  void add (const ElementType& newElement)
419  {
420  const ScopedLockType lock (getLock());
421  values.add (newElement);
422  }
423 
428  void add (ElementType&& newElement)
429  {
430  const ScopedLockType lock (getLock());
431  values.add (std::move (newElement));
432  }
433 
435  template <typename... OtherElements>
436  void add (const ElementType& firstNewElement, OtherElements... otherElements)
437  {
438  const ScopedLockType lock (getLock());
439  values.add (firstNewElement, otherElements...);
440  }
441 
443  template <typename... OtherElements>
444  void add (ElementType&& firstNewElement, OtherElements... otherElements)
445  {
446  const ScopedLockType lock (getLock());
447  values.add (std::move (firstNewElement), otherElements...);
448  }
449 
462  void insert (int indexToInsertAt, ParameterType newElement)
463  {
464  const ScopedLockType lock (getLock());
465  values.insert (indexToInsertAt, newElement, 1);
466  }
467 
480  void insertMultiple (int indexToInsertAt, ParameterType newElement,
481  int numberOfTimesToInsertIt)
482  {
483  if (numberOfTimesToInsertIt > 0)
484  {
485  const ScopedLockType lock (getLock());
486  values.insert (indexToInsertAt, newElement, numberOfTimesToInsertIt);
487  }
488  }
489 
502  void insertArray (int indexToInsertAt,
503  const ElementType* newElements,
504  int numberOfElements)
505  {
506  if (numberOfElements > 0)
507  {
508  const ScopedLockType lock (getLock());
509  values.insertArray (indexToInsertAt, newElements, numberOfElements);
510  }
511  }
512 
522  bool addIfNotAlreadyThere (ParameterType newElement)
523  {
524  const ScopedLockType lock (getLock());
525 
526  if (contains (newElement))
527  return false;
528 
529  add (newElement);
530  return true;
531  }
532 
542  void set (int indexToChange, ParameterType newValue)
543  {
544  if (indexToChange >= 0)
545  {
546  const ScopedLockType lock (getLock());
547 
548  if (indexToChange < values.size())
549  values[indexToChange] = newValue;
550  else
551  values.add (newValue);
552  }
553  else
554  {
555  jassertfalse;
556  }
557  }
558 
568  void setUnchecked (int indexToChange, ParameterType newValue)
569  {
570  const ScopedLockType lock (getLock());
571  jassert (isPositiveAndBelow (indexToChange, values.size()));
572  values[indexToChange] = newValue;
573  }
574 
582  template <typename Type>
583  void addArray (const Type* elementsToAdd, int numElementsToAdd)
584  {
585  const ScopedLockType lock (getLock());
586 
587  if (numElementsToAdd > 0)
588  values.addArray (elementsToAdd, numElementsToAdd);
589  }
590 
591  template <typename TypeToCreateFrom>
592  void addArray (const std::initializer_list<TypeToCreateFrom>& items)
593  {
594  const ScopedLockType lock (getLock());
595  values.addArray (items);
596  }
597 
604  template <typename Type>
605  void addNullTerminatedArray (const Type* const* elementsToAdd)
606  {
607  int num = 0;
608 
609  for (auto e = elementsToAdd; *e != nullptr; ++e)
610  ++num;
611 
612  addArray (elementsToAdd, num);
613  }
614 
620  template <class OtherArrayType>
621  void swapWith (OtherArrayType& otherArray) noexcept
622  {
623  const ScopedLockType lock1 (getLock());
624  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
625  values.swapWith (otherArray.values);
626  }
627 
633  template <class OtherArrayType>
634  void addArray (const OtherArrayType& arrayToAddFrom)
635  {
636  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
637  const ScopedLockType lock2 (getLock());
638 
639  values.addArray (arrayToAddFrom);
640  }
641 
651  template <class OtherArrayType>
652  typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type
653  addArray (const OtherArrayType& arrayToAddFrom,
654  int startIndex,
655  int numElementsToAdd = -1)
656  {
657  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
658  const ScopedLockType lock2 (getLock());
659 
660  values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
661  }
662 
670  void resize (int targetNumItems)
671  {
672  jassert (targetNumItems >= 0);
673  auto numToAdd = targetNumItems - values.size();
674 
675  if (numToAdd > 0)
676  insertMultiple (values.size(), ElementType(), numToAdd);
677  else if (numToAdd < 0)
678  removeRange (targetNumItems, -numToAdd);
679  }
680 
693  template <class ElementComparator>
694  int addSorted (ElementComparator& comparator, ParameterType newElement)
695  {
696  const ScopedLockType lock (getLock());
697  auto index = findInsertIndexInSortedArray (comparator, values.begin(), newElement, 0, values.size());
698  insert (index, newElement);
699  return index;
700  }
701 
711  void addUsingDefaultSort (ParameterType newElement)
712  {
714  addSorted (comparator, newElement);
715  }
716 
729  template <typename ElementComparator, typename TargetValueType>
730  int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const
731  {
732  ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
733  // avoids getting warning messages about the parameter being unused
734 
735  const ScopedLockType lock (getLock());
736 
737  for (int s = 0, e = values.size();;)
738  {
739  if (s >= e)
740  return -1;
741 
742  if (comparator.compareElements (elementToLookFor, values[s]) == 0)
743  return s;
744 
745  auto halfway = (s + e) / 2;
746 
747  if (halfway == s)
748  return -1;
749 
750  if (comparator.compareElements (elementToLookFor, values[halfway]) >= 0)
751  s = halfway;
752  else
753  e = halfway;
754  }
755  }
756 
757  //==============================================================================
767  void remove (int indexToRemove)
768  {
769  const ScopedLockType lock (getLock());
770 
771  if (isPositiveAndBelow (indexToRemove, values.size()))
772  removeInternal (indexToRemove);
773  }
774 
785  ElementType removeAndReturn (int indexToRemove)
786  {
787  const ScopedLockType lock (getLock());
788 
789  if (isPositiveAndBelow (indexToRemove, values.size()))
790  {
791  ElementType removed (values[indexToRemove]);
792  removeInternal (indexToRemove);
793  return removed;
794  }
795 
796  return ElementType();
797  }
798 
809  void remove (const ElementType* elementToRemove)
810  {
811  jassert (elementToRemove != nullptr);
812  const ScopedLockType lock (getLock());
813 
814  jassert (values.begin() != nullptr);
815  auto indexToRemove = (int) (elementToRemove - values.begin());
816 
817  if (! isPositiveAndBelow (indexToRemove, values.size()))
818  {
819  jassertfalse;
820  return;
821  }
822 
823  removeInternal (indexToRemove);
824  }
825 
834  void removeFirstMatchingValue (ParameterType valueToRemove)
835  {
836  const ScopedLockType lock (getLock());
837  auto* e = values.begin();
838 
839  for (int i = 0; i < values.size(); ++i)
840  {
841  if (valueToRemove == e[i])
842  {
843  removeInternal (i);
844  break;
845  }
846  }
847  }
848 
858  int removeAllInstancesOf (ParameterType valueToRemove)
859  {
860  int numRemoved = 0;
861  const ScopedLockType lock (getLock());
862 
863  for (int i = values.size(); --i >= 0;)
864  {
865  if (valueToRemove == values[i])
866  {
867  removeInternal (i);
868  ++numRemoved;
869  }
870  }
871 
872  return numRemoved;
873  }
874 
886  template <typename PredicateType>
887  int removeIf (PredicateType&& predicate)
888  {
889  int numRemoved = 0;
890  const ScopedLockType lock (getLock());
891 
892  for (int i = values.size(); --i >= 0;)
893  {
894  if (predicate (values[i]))
895  {
896  removeInternal (i);
897  ++numRemoved;
898  }
899  }
900 
901  return numRemoved;
902  }
903 
916  void removeRange (int startIndex, int numberToRemove)
917  {
918  const ScopedLockType lock (getLock());
919 
920  auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
921  startIndex = jlimit (0, values.size(), startIndex);
922  numberToRemove = endIndex - startIndex;
923 
924  if (numberToRemove > 0)
925  {
926  values.removeElements (startIndex, numberToRemove);
927  minimiseStorageAfterRemoval();
928  }
929  }
930 
936  void removeLast (int howManyToRemove = 1)
937  {
938  jassert (howManyToRemove >= 0);
939 
940  if (howManyToRemove > 0)
941  {
942  const ScopedLockType lock (getLock());
943 
944  if (howManyToRemove > values.size())
945  howManyToRemove = values.size();
946 
947  values.removeElements (values.size() - howManyToRemove, howManyToRemove);
948  minimiseStorageAfterRemoval();
949  }
950  }
951 
957  template <class OtherArrayType>
958  void removeValuesIn (const OtherArrayType& otherArray)
959  {
960  const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
961  const ScopedLockType lock2 (getLock());
962 
963  if (this == &otherArray)
964  {
965  clear();
966  }
967  else
968  {
969  if (otherArray.size() > 0)
970  {
971  for (int i = values.size(); --i >= 0;)
972  if (otherArray.contains (values[i]))
973  removeInternal (i);
974  }
975  }
976  }
977 
985  template <class OtherArrayType>
986  void removeValuesNotIn (const OtherArrayType& otherArray)
987  {
988  const typename OtherArrayType::ScopedLockType lock1 (otherArray.getLock());
989  const ScopedLockType lock2 (getLock());
990 
991  if (this != &otherArray)
992  {
993  if (otherArray.size() <= 0)
994  {
995  clear();
996  }
997  else
998  {
999  for (int i = values.size(); --i >= 0;)
1000  if (! otherArray.contains (values[i]))
1001  removeInternal (i);
1002  }
1003  }
1004  }
1005 
1014  void swap (int index1, int index2)
1015  {
1016  const ScopedLockType lock (getLock());
1017  values.swap (index1, index2);
1018  }
1019 
1034  void move (int currentIndex, int newIndex) noexcept
1035  {
1036  if (currentIndex != newIndex)
1037  {
1038  const ScopedLockType lock (getLock());
1039  values.move (currentIndex, newIndex);
1040  }
1041  }
1042 
1043  //==============================================================================
1051  {
1052  const ScopedLockType lock (getLock());
1053  values.shrinkToNoMoreThan (values.size());
1054  }
1055 
1062  void ensureStorageAllocated (int minNumElements)
1063  {
1064  const ScopedLockType lock (getLock());
1065  values.ensureAllocatedSize (minNumElements);
1066  }
1067 
1068  //==============================================================================
1073  void sort()
1074  {
1076  sort (comparator);
1077  }
1078 
1105  template <class ElementComparator>
1106  void sort (ElementComparator& comparator,
1107  bool retainOrderOfEquivalentItems = false)
1108  {
1109  const ScopedLockType lock (getLock());
1110  ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this
1111  // avoids getting warning messages about the parameter being unused
1112  sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
1113  }
1114 
1115  //==============================================================================
1120  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
1121 
1123  using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
1124 
1125 
1126  //==============================================================================
1127  #ifndef DOXYGEN
1128  // Note that the swapWithArray method has been replaced by a more flexible templated version,
1129  // and renamed "swapWith" to be more consistent with the names used in other classes.
1130  JUCE_DEPRECATED_WITH_BODY (void swapWithArray (Array& other) noexcept, { swapWith (other); })
1131  #endif
1132 
1133 private:
1134  //==============================================================================
1136 
1137  void removeInternal (int indexToRemove)
1138  {
1139  values.removeElements (indexToRemove, 1);
1140  minimiseStorageAfterRemoval();
1141  }
1142 
1143  void minimiseStorageAfterRemoval()
1144  {
1145  if (values.capacity() > jmax (minimumAllocatedSize, values.size() * 2))
1146  values.shrinkToNoMoreThan (jmax (values.size(), jmax (minimumAllocatedSize, 64 / (int) sizeof (ElementType))));
1147  }
1148 };
1149 
1150 } // namespace juce
void sort()
Definition: juce_Array.h:1073
void removeValuesNotIn(const OtherArrayType &otherArray)
Definition: juce_Array.h:986
int removeIf(PredicateType &&predicate)
Definition: juce_Array.h:887
void removeFirstMatchingValue(ParameterType valueToRemove)
Definition: juce_Array.h:834
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition: juce_Array.h:583
const ElementType * data() const noexcept
Definition: juce_Array.h:368
Array & operator=(const Array &other)
Definition: juce_Array.h:137
ElementType * end() noexcept
Definition: juce_Array.h:344
void minimiseStorageOverheads()
Definition: juce_Array.h:1050
void swapWith(OtherArrayType &otherArray) noexcept
Definition: juce_Array.h:621
void fill(const ParameterType &newValue) noexcept
Definition: juce_Array.h:205
void clearQuick()
Definition: juce_Array.h:198
void insertArray(int indexToInsertAt, const ElementType *newElements, int numberOfElements)
Definition: juce_Array.h:502
typename DummyCriticalSection ::ScopedLockType ScopedLockType
Definition: juce_Array.h:1123
int indexOf(ParameterType elementToLookFor) const
Definition: juce_Array.h:382
bool addIfNotAlreadyThere(ParameterType newElement)
Definition: juce_Array.h:522
Array(const ElementType &firstNewElement, OtherElements... otherElements)
Definition: juce_Array.h:113
void removeValuesIn(const OtherArrayType &otherArray)
Definition: juce_Array.h:958
void ensureStorageAllocated(int minNumElements)
Definition: juce_Array.h:1062
void swap(int index1, int index2)
Definition: juce_Array.h:1014
void add(ElementType &&newElement)
Definition: juce_Array.h:428
void add(const ElementType &newElement)
Definition: juce_Array.h:418
void add(const ElementType &firstNewElement, OtherElements... otherElements)
Definition: juce_Array.h:436
ElementType getLast() const noexcept
Definition: juce_Array.h:300
ElementType * data() noexcept
Definition: juce_Array.h:360
const ElementType & getReference(int index) const noexcept
Definition: juce_Array.h:281
void addArray(const OtherArrayType &arrayToAddFrom)
Definition: juce_Array.h:634
void move(int currentIndex, int newIndex) noexcept
Definition: juce_Array.h:1034
Array(const TypeToCreateFrom *data)
Definition: juce_Array.h:83
Array(const ElementType &singleElementToAdd)
Definition: juce_Array.h:100
ElementType operator[](int index) const
Definition: juce_Array.h:237
Array(const TypeToCreateFrom *data, int numValues)
Definition: juce_Array.h:94
void insert(int indexToInsertAt, ParameterType newElement)
Definition: juce_Array.h:462
void resize(int targetNumItems)
Definition: juce_Array.h:670
ElementType getUnchecked(int index) const
Definition: juce_Array.h:252
void addNullTerminatedArray(const Type *const *elementsToAdd)
Definition: juce_Array.h:605
int addSorted(ElementComparator &comparator, ParameterType newElement)
Definition: juce_Array.h:694
Array(const Array &other)
Definition: juce_Array.h:68
const ElementType * begin() const noexcept
Definition: juce_Array.h:336
Array(ElementType &&singleElementToAdd)
Definition: juce_Array.h:106
bool operator!=(const OtherArrayType &other) const
Definition: juce_Array.h:175
ElementType * begin() noexcept
Definition: juce_Array.h:328
void insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
Definition: juce_Array.h:480
Array()=default
void add(ElementType &&firstNewElement, OtherElements... otherElements)
Definition: juce_Array.h:444
void removeLast(int howManyToRemove=1)
Definition: juce_Array.h:936
void setUnchecked(int indexToChange, ParameterType newValue)
Definition: juce_Array.h:568
void addUsingDefaultSort(ParameterType newElement)
Definition: juce_Array.h:711
~Array()=default
void clear()
Definition: juce_Array.h:188
int size() const noexcept
Definition: juce_Array.h:215
ElementType removeAndReturn(int indexToRemove)
Definition: juce_Array.h:785
const TypeOfCriticalSectionToUse & getLock() const noexcept
Definition: juce_Array.h:1120
ElementType getFirst() const noexcept
Definition: juce_Array.h:290
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:310
const ElementType * end() const noexcept
Definition: juce_Array.h:352
ElementType & getReference(int index) noexcept
Definition: juce_Array.h:267
bool isEmpty() const noexcept
Definition: juce_Array.h:222
Array(ElementType &&firstNewElement, OtherElements... otherElements)
Definition: juce_Array.h:120
int indexOfSorted(ElementComparator &comparator, TargetValueType elementToLookFor) const
Definition: juce_Array.h:730
const ElementType * getRawDataPointer() const noexcept
Definition: juce_Array.h:319
int removeAllInstancesOf(ParameterType valueToRemove)
Definition: juce_Array.h:858
bool contains(ParameterType elementToLookFor) const
Definition: juce_Array.h:400
std::enable_if<! std::is_pointer< OtherArrayType >::value, void >::type addArray(const OtherArrayType &arrayToAddFrom, int startIndex, int numElementsToAdd=-1)
Definition: juce_Array.h:653
void removeRange(int startIndex, int numberToRemove)
Definition: juce_Array.h:916
bool operator==(const OtherArrayType &other) const
Definition: juce_Array.h:162
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false)
Definition: juce_Array.h:1106