OpenShot Audio Library | OpenShotAudio  0.3.2
juce_OwnedArray.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 //==============================================================================
47 template <class ObjectClass,
48  class TypeOfCriticalSectionToUse = DummyCriticalSection>
49 
51 {
52 public:
53  //==============================================================================
55  OwnedArray() = default;
56 
63  {
64  deleteAllObjects();
65  }
66 
68  OwnedArray (OwnedArray&& other) noexcept
69  : values (std::move (other.values))
70  {
71  }
72 
74  OwnedArray (const std::initializer_list<ObjectClass*>& items)
75  {
76  addArray (items);
77  }
78 
80  OwnedArray& operator= (OwnedArray&& other) noexcept
81  {
82  const ScopedLockType lock (getLock());
83  deleteAllObjects();
84  values = std::move (other.values);
85  return *this;
86  }
87 
89  template <class OtherObjectClass, class OtherCriticalSection>
91  : values (std::move (other.values))
92  {
93  }
94 
96  template <class OtherObjectClass, class OtherCriticalSection>
98  {
99  const ScopedLockType lock (getLock());
100  deleteAllObjects();
101  values = std::move (other.values);
102  return *this;
103  }
104 
105  //==============================================================================
107  void clear (bool deleteObjects = true)
108  {
109  const ScopedLockType lock (getLock());
110  clearQuick (deleteObjects);
111  values.setAllocatedSize (0);
112  }
113 
114  //==============================================================================
116  void clearQuick (bool deleteObjects)
117  {
118  const ScopedLockType lock (getLock());
119 
120  if (deleteObjects)
121  deleteAllObjects();
122  else
123  values.clear();
124  }
125 
126  //==============================================================================
130  inline int size() const noexcept
131  {
132  return values.size();
133  }
134 
136  inline bool isEmpty() const noexcept
137  {
138  return size() == 0;
139  }
140 
149  inline ObjectClass* operator[] (int index) const noexcept
150  {
151  const ScopedLockType lock (getLock());
152  return values.getValueWithDefault (index);
153  }
154 
160  inline ObjectClass* getUnchecked (int index) const noexcept
161  {
162  const ScopedLockType lock (getLock());
163  return values[index];
164  }
165 
171  inline ObjectClass* getFirst() const noexcept
172  {
173  const ScopedLockType lock (getLock());
174  return values.getFirst();
175  }
176 
182  inline ObjectClass* getLast() const noexcept
183  {
184  const ScopedLockType lock (getLock());
185  return values.getLast();
186  }
187 
192  inline ObjectClass** getRawDataPointer() noexcept
193  {
194  return values.begin();
195  }
196 
197  //==============================================================================
201  inline ObjectClass** begin() noexcept
202  {
203  return values.begin();
204  }
205 
209  inline ObjectClass* const* begin() const noexcept
210  {
211  return values.begin();
212  }
213 
217  inline ObjectClass** end() noexcept
218  {
219  return values.end();
220  }
221 
225  inline ObjectClass* const* end() const noexcept
226  {
227  return values.end();
228  }
229 
233  inline ObjectClass** data() noexcept
234  {
235  return begin();
236  }
237 
241  inline ObjectClass* const* data() const noexcept
242  {
243  return begin();
244  }
245 
246  //==============================================================================
252  int indexOf (const ObjectClass* objectToLookFor) const noexcept
253  {
254  const ScopedLockType lock (getLock());
255  auto* e = values.begin();
256 
257  for (; e != values.end(); ++e)
258  if (objectToLookFor == *e)
259  return static_cast<int> (e - values.begin());
260 
261  return -1;
262  }
263 
269  bool contains (const ObjectClass* objectToLookFor) const noexcept
270  {
271  const ScopedLockType lock (getLock());
272  auto* e = values.begin();
273 
274  for (; e != values.end(); ++e)
275  if (objectToLookFor == *e)
276  return true;
277 
278  return false;
279  }
280 
281  //==============================================================================
294  ObjectClass* add (ObjectClass* newObject)
295  {
296  const ScopedLockType lock (getLock());
297  values.add (newObject);
298  return newObject;
299  }
300 
313  ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
314  {
315  return add (newObject.release());
316  }
317 
336  ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
337  {
338  const ScopedLockType lock (getLock());
339  values.insert (indexToInsertAt, newObject, 1);
340  return newObject;
341  }
342 
361  ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
362  {
363  return insert (indexToInsertAt, newObject.release());
364  }
365 
378  void insertArray (int indexToInsertAt,
379  ObjectClass* const* newObjects,
380  int numberOfElements)
381  {
382  if (numberOfElements > 0)
383  {
384  const ScopedLockType lock (getLock());
385  values.insertArray (indexToInsertAt, newObjects, numberOfElements);
386  }
387  }
388 
402  ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
403  {
404  if (indexToChange >= 0)
405  {
406  std::unique_ptr<ObjectClass> toDelete;
407 
408  {
409  const ScopedLockType lock (getLock());
410 
411  if (indexToChange < values.size())
412  {
413  if (deleteOldElement)
414  {
415  toDelete.reset (values[indexToChange]);
416 
417  if (toDelete.get() == newObject)
418  toDelete.release();
419  }
420 
421  values[indexToChange] = newObject;
422  }
423  else
424  {
425  values.add (newObject);
426  }
427  }
428  }
429  else
430  {
431  jassertfalse; // you're trying to set an object at a negative index, which doesn't have
432  // any effect - but since the object is not being added, it may be leaking..
433  }
434 
435  return newObject;
436  }
437 
451  ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
452  {
453  return set (indexToChange, newObject.release(), deleteOldElement);
454  }
455 
465  template <class OtherArrayType>
466  void addArray (const OtherArrayType& arrayToAddFrom,
467  int startIndex = 0,
468  int numElementsToAdd = -1)
469  {
470  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
471  const ScopedLockType lock2 (getLock());
472  values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
473  }
474 
476  template <typename OtherArrayType>
477  void addArray (const std::initializer_list<OtherArrayType>& items)
478  {
479  const ScopedLockType lock (getLock());
480  values.addArray (items);
481  }
482 
497  template <class OtherArrayType>
498  void addCopiesOf (const OtherArrayType& arrayToAddFrom,
499  int startIndex = 0,
500  int numElementsToAdd = -1)
501  {
502  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
503  const ScopedLockType lock2 (getLock());
504 
505  if (startIndex < 0)
506  {
507  jassertfalse;
508  startIndex = 0;
509  }
510 
511  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
512  numElementsToAdd = arrayToAddFrom.size() - startIndex;
513 
514  jassert (numElementsToAdd >= 0);
515  values.ensureAllocatedSize (values.size() + numElementsToAdd);
516 
517  while (--numElementsToAdd >= 0)
518  values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
519  }
520 
533  template <class ElementComparator>
534  int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
535  {
536  // If you pass in an object with a static compareElements() method, this
537  // avoids getting warning messages about the parameter being unused
538  ignoreUnused (comparator);
539 
540  const ScopedLockType lock (getLock());
541  auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
542  insert (index, newObject);
543  return index;
544  }
545 
558  template <typename ElementComparator>
559  int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept
560  {
561  // If you pass in an object with a static compareElements() method, this
562  // avoids getting warning messages about the parameter being unused
563  ignoreUnused (comparator);
564 
565  const ScopedLockType lock (getLock());
566  int s = 0, e = values.size();
567 
568  while (s < e)
569  {
570  if (comparator.compareElements (objectToLookFor, values[s]) == 0)
571  return s;
572 
573  auto halfway = (s + e) / 2;
574 
575  if (halfway == s)
576  break;
577 
578  if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
579  s = halfway;
580  else
581  e = halfway;
582  }
583 
584  return -1;
585  }
586 
587  //==============================================================================
598  void remove (int indexToRemove, bool deleteObject = true)
599  {
600  std::unique_ptr<ObjectClass> toDelete;
601 
602  {
603  const ScopedLockType lock (getLock());
604 
605  if (isPositiveAndBelow (indexToRemove, values.size()))
606  {
607  auto** e = values.begin() + indexToRemove;
608 
609  if (deleteObject)
610  toDelete.reset (*e);
611 
612  values.removeElements (indexToRemove, 1);
613  }
614  }
615 
616  if ((values.size() << 1) < values.capacity())
618  }
619 
629  ObjectClass* removeAndReturn (int indexToRemove)
630  {
631  ObjectClass* removedItem = nullptr;
632  const ScopedLockType lock (getLock());
633 
634  if (isPositiveAndBelow (indexToRemove, values.size()))
635  {
636  removedItem = values[indexToRemove];
637 
638  values.removeElements (indexToRemove, 1);
639 
640  if ((values.size() << 1) < values.capacity())
642  }
643 
644  return removedItem;
645  }
646 
655  void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
656  {
657  const ScopedLockType lock (getLock());
658 
659  for (int i = 0; i < values.size(); ++i)
660  {
661  if (objectToRemove == values[i])
662  {
663  remove (i, deleteObject);
664  break;
665  }
666  }
667  }
668 
682  void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
683  {
684  const ScopedLockType lock (getLock());
685  auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
686  startIndex = jlimit (0, values.size(), startIndex);
687  numberToRemove = endIndex - startIndex;
688 
689  if (numberToRemove > 0)
690  {
691  Array<ObjectClass*> objectsToDelete;
692 
693  if (deleteObjects)
694  objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
695 
696  values.removeElements (startIndex, numberToRemove);
697 
698  for (auto& o : objectsToDelete)
700 
701  if ((values.size() << 1) < values.capacity())
703  }
704  }
705 
712  void removeLast (int howManyToRemove = 1,
713  bool deleteObjects = true)
714  {
715  const ScopedLockType lock (getLock());
716 
717  if (howManyToRemove >= values.size())
718  clear (deleteObjects);
719  else
720  removeRange (values.size() - howManyToRemove, howManyToRemove, deleteObjects);
721  }
722 
728  void swap (int index1, int index2) noexcept
729  {
730  const ScopedLockType lock (getLock());
731  values.swap (index1, index2);
732  }
733 
747  void move (int currentIndex, int newIndex) noexcept
748  {
749  if (currentIndex != newIndex)
750  {
751  const ScopedLockType lock (getLock());
752  values.move (currentIndex, newIndex);
753  }
754  }
755 
761  template <class OtherArrayType>
762  void swapWith (OtherArrayType& otherArray) noexcept
763  {
764  const ScopedLockType lock1 (getLock());
765  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
766  values.swapWith (otherArray.values);
767  }
768 
769  //==============================================================================
776  void minimiseStorageOverheads() noexcept
777  {
778  const ScopedLockType lock (getLock());
779  values.shrinkToNoMoreThan (values.size());
780  }
781 
788  void ensureStorageAllocated (int minNumElements) noexcept
789  {
790  const ScopedLockType lock (getLock());
791  values.ensureAllocatedSize (minNumElements);
792  }
793 
794  //==============================================================================
820  template <class ElementComparator>
821  void sort (ElementComparator& comparator,
822  bool retainOrderOfEquivalentItems = false) noexcept
823  {
824  // If you pass in an object with a static compareElements() method, this
825  // avoids getting warning messages about the parameter being unused
826  ignoreUnused (comparator);
827 
828  const ScopedLockType lock (getLock());
829 
830  if (size() > 1)
831  sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
832  }
833 
834  //==============================================================================
839  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
840 
842  using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
843 
844  //==============================================================================
845  #ifndef DOXYGEN
846  // Note that the swapWithArray method has been replaced by a more flexible templated version,
847  // and renamed "swapWith" to be more consistent with the names used in other classes.
848  JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
849  #endif
850 
851 private:
852  //==============================================================================
854 
855  void deleteAllObjects()
856  {
857  auto i = values.size();
858 
859  while (--i >= 0)
860  {
861  auto* e = values[i];
862  values.removeElements (i, 1);
864  }
865  }
866 
867  template <class OtherObjectClass, class OtherCriticalSection>
868  friend class OwnedArray;
869 
870  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
871 };
872 
873 } // namespace juce
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition: juce_Array.h:583
int size() const noexcept
ObjectClass * insert(int indexToInsertAt, std::unique_ptr< ObjectClass > newObject)
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
bool isEmpty() const noexcept
void swapWith(OtherArrayType &otherArray) noexcept
OwnedArray & operator=(OwnedArray &&other) noexcept
void remove(int indexToRemove, bool deleteObject=true)
ObjectClass ** data() noexcept
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
void ensureStorageAllocated(int minNumElements) noexcept
ObjectClass *const * begin() const noexcept
void minimiseStorageOverheads() noexcept
void clear(bool deleteObjects=true)
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
int indexOf(const ObjectClass *objectToLookFor) const noexcept
ObjectClass * removeAndReturn(int indexToRemove)
OwnedArray(OwnedArray< OtherObjectClass, OtherCriticalSection > &&other) noexcept
const TypeOfCriticalSectionToUse & getLock() const noexcept
ObjectClass *const * data() const noexcept
void swap(int index1, int index2) noexcept
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
ObjectClass * getUnchecked(int index) const noexcept
ObjectClass * operator[](int index) const noexcept
void clearQuick(bool deleteObjects)
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
ObjectClass * getLast() const noexcept
ObjectClass * set(int indexToChange, std::unique_ptr< ObjectClass > newObject, bool deleteOldElement=true)
ObjectClass * add(std::unique_ptr< ObjectClass > newObject)
ObjectClass *const * end() const noexcept
OwnedArray()=default
ObjectClass * getFirst() const noexcept
ObjectClass ** end() noexcept
OwnedArray(OwnedArray &&other) noexcept
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
void move(int currentIndex, int newIndex) noexcept
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
void addArray(const std::initializer_list< OtherArrayType > &items)
ObjectClass ** getRawDataPointer() noexcept
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
OwnedArray(const std::initializer_list< ObjectClass * > &items)
ObjectClass ** begin() noexcept
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
ObjectClass * set(int indexToChange, ObjectClass *newObject, bool deleteOldElement=true)
ObjectClass * add(ObjectClass *newObject)
bool contains(const ObjectClass *objectToLookFor) const noexcept