OpenShot Library | OpenShotAudio  0.2.2
juce_OwnedArray.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 /** An array designed for holding objects.
32 
33  This holds a list of pointers to objects, and will automatically
34  delete the objects when they are removed from the array, or when the
35  array is itself deleted.
36 
37  Declare it in the form: OwnedArray<MyObjectClass>
38 
39  ..and then add new objects, e.g. myOwnedArray.add (new MyObjectClass());
40 
41  After adding objects, they are 'owned' by the array and will be deleted when
42  removed or replaced.
43 
44  To make all the array's methods thread-safe, pass in "CriticalSection" as the templated
45  TypeOfCriticalSectionToUse parameter, instead of the default DummyCriticalSection.
46 
47  @see Array, ReferenceCountedArray, StringArray, CriticalSection
48 
49  @tags{Core}
50 */
51 template <class ObjectClass,
52  class TypeOfCriticalSectionToUse = DummyCriticalSection>
53 
55 {
56 public:
57  //==============================================================================
58  /** Creates an empty array. */
59  OwnedArray() = default;
60 
61  /** Deletes the array and also deletes any objects inside it.
62 
63  To get rid of the array without deleting its objects, use its
64  clear (false) method before deleting it.
65  */
67  {
68  deleteAllObjects();
69  }
70 
71  /** Move constructor. */
72  OwnedArray (OwnedArray&& other) noexcept
73  : values (std::move (other.values))
74  {
75  }
76 
77  /** Creates an array from a list of objects. */
78  OwnedArray (const std::initializer_list<ObjectClass*>& items)
79  {
80  addArray (items);
81  }
82 
83  /** Move assignment operator. */
84  OwnedArray& operator= (OwnedArray&& other) noexcept
85  {
86  const ScopedLockType lock (getLock());
87  deleteAllObjects();
88  values = std::move (other.values);
89  return *this;
90  }
91 
92  /** Converting move constructor. */
93  template <class OtherObjectClass, class OtherCriticalSection>
95  : values (std::move (other.values))
96  {
97  }
98 
99  /** Converting move assignment operator. */
100  template <class OtherObjectClass, class OtherCriticalSection>
102  {
103  const ScopedLockType lock (getLock());
104  deleteAllObjects();
105  values = std::move (other.values);
106  return *this;
107  }
108 
109  //==============================================================================
110  /** Clears the array, optionally deleting the objects inside it first. */
111  void clear (bool deleteObjects = true)
112  {
113  const ScopedLockType lock (getLock());
114  clearQuick (deleteObjects);
115  values.setAllocatedSize (0);
116  }
117 
118  //==============================================================================
119  /** Clears the array, optionally deleting the objects inside it first. */
120  void clearQuick (bool deleteObjects)
121  {
122  const ScopedLockType lock (getLock());
123 
124  if (deleteObjects)
125  deleteAllObjects();
126  else
127  values.clear();
128  }
129 
130  //==============================================================================
131  /** Returns the number of items currently in the array.
132  @see operator[]
133  */
134  inline int size() const noexcept
135  {
136  return values.size();
137  }
138 
139  /** Returns true if the array is empty, false otherwise. */
140  inline bool isEmpty() const noexcept
141  {
142  return size() == 0;
143  }
144 
145  /** Returns a pointer to the object at this index in the array.
146 
147  If the index is out-of-range, this will return a null pointer, (and
148  it could be null anyway, because it's ok for the array to hold null
149  pointers as well as objects).
150 
151  @see getUnchecked
152  */
153  inline ObjectClass* operator[] (int index) const noexcept
154  {
155  const ScopedLockType lock (getLock());
156  return values.getValueWithDefault (index);
157  }
158 
159  /** Returns a pointer to the object at this index in the array, without checking whether the index is in-range.
160 
161  This is a faster and less safe version of operator[] which doesn't check the index passed in, so
162  it can be used when you're sure the index is always going to be legal.
163  */
164  inline ObjectClass* getUnchecked (int index) const noexcept
165  {
166  const ScopedLockType lock (getLock());
167  return values[index];
168  }
169 
170  /** Returns a pointer to the first object in the array.
171 
172  This will return a null pointer if the array's empty.
173  @see getLast
174  */
175  inline ObjectClass* getFirst() const noexcept
176  {
177  const ScopedLockType lock (getLock());
178  return values.getFirst();
179  }
180 
181  /** Returns a pointer to the last object in the array.
182 
183  This will return a null pointer if the array's empty.
184  @see getFirst
185  */
186  inline ObjectClass* getLast() const noexcept
187  {
188  const ScopedLockType lock (getLock());
189  return values.getLast();
190  }
191 
192  /** Returns a pointer to the actual array data.
193  This pointer will only be valid until the next time a non-const method
194  is called on the array.
195  */
196  inline ObjectClass** getRawDataPointer() noexcept
197  {
198  return values.begin();
199  }
200 
201  //==============================================================================
202  /** Returns a pointer to the first element in the array.
203  This method is provided for compatibility with standard C++ iteration mechanisms.
204  */
205  inline ObjectClass** begin() noexcept
206  {
207  return values.begin();
208  }
209 
210  /** Returns a pointer to the first element in the array.
211  This method is provided for compatibility with standard C++ iteration mechanisms.
212  */
213  inline ObjectClass* const* begin() const noexcept
214  {
215  return values.begin();
216  }
217 
218  /** Returns a pointer to the element which follows the last element in the array.
219  This method is provided for compatibility with standard C++ iteration mechanisms.
220  */
221  inline ObjectClass** end() noexcept
222  {
223  return values.end();
224  }
225 
226  /** Returns a pointer to the element which follows the last element in the array.
227  This method is provided for compatibility with standard C++ iteration mechanisms.
228  */
229  inline ObjectClass* const* end() const noexcept
230  {
231  return values.end();
232  }
233 
234  /** Returns a pointer to the first element in the array.
235  This method is provided for compatibility with the standard C++ containers.
236  */
237  inline ObjectClass** data() noexcept
238  {
239  return begin();
240  }
241 
242  /** Returns a pointer to the first element in the array.
243  This method is provided for compatibility with the standard C++ containers.
244  */
245  inline ObjectClass* const* data() const noexcept
246  {
247  return begin();
248  }
249 
250  //==============================================================================
251  /** Finds the index of an object which might be in the array.
252 
253  @param objectToLookFor the object to look for
254  @returns the index at which the object was found, or -1 if it's not found
255  */
256  int indexOf (const ObjectClass* objectToLookFor) const noexcept
257  {
258  const ScopedLockType lock (getLock());
259  auto* e = values.begin();
260 
261  for (; e != values.end(); ++e)
262  if (objectToLookFor == *e)
263  return static_cast<int> (e - values.begin());
264 
265  return -1;
266  }
267 
268  /** Returns true if the array contains a specified object.
269 
270  @param objectToLookFor the object to look for
271  @returns true if the object is in the array
272  */
273  bool contains (const ObjectClass* objectToLookFor) const noexcept
274  {
275  const ScopedLockType lock (getLock());
276  auto* e = values.begin();
277 
278  for (; e != values.end(); ++e)
279  if (objectToLookFor == *e)
280  return true;
281 
282  return false;
283  }
284 
285  //==============================================================================
286  /** Appends a new object to the end of the array.
287 
288  Note that this object will be deleted by the OwnedArray when it is removed,
289  so be careful not to delete it somewhere else.
290 
291  Also be careful not to add the same object to the array more than once,
292  as this will obviously cause deletion of dangling pointers.
293 
294  @param newObject the new object to add to the array
295  @returns the new object that was added
296  @see set, insert, addSorted
297  */
298  ObjectClass* add (ObjectClass* newObject)
299  {
300  const ScopedLockType lock (getLock());
301  values.add (newObject);
302  return newObject;
303  }
304 
305  /** Appends a new object to the end of the array.
306 
307  Note that this object will be deleted by the OwnedArray when it is removed,
308  so be careful not to delete it somewhere else.
309 
310  Also be careful not to add the same object to the array more than once,
311  as this will obviously cause deletion of dangling pointers.
312 
313  @param newObject the new object to add to the array
314  @returns the new object that was added
315  @see set, insert, addSorted
316  */
317  ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
318  {
319  return add (newObject.release());
320  }
321 
322  /** Inserts a new object into the array at the given index.
323 
324  Note that this object will be deleted by the OwnedArray when it is removed,
325  so be careful not to delete it somewhere else.
326 
327  If the index is less than 0 or greater than the size of the array, the
328  element will be added to the end of the array.
329  Otherwise, it will be inserted into the array, moving all the later elements
330  along to make room.
331 
332  Be careful not to add the same object to the array more than once,
333  as this will obviously cause deletion of dangling pointers.
334 
335  @param indexToInsertAt the index at which the new element should be inserted
336  @param newObject the new object to add to the array
337  @returns the new object that was added
338  @see add, addSorted, set
339  */
340  ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
341  {
342  const ScopedLockType lock (getLock());
343  values.insert (indexToInsertAt, newObject, 1);
344  return newObject;
345  }
346 
347  /** Inserts a new object into the array at the given index.
348 
349  Note that this object will be deleted by the OwnedArray when it is removed,
350  so be careful not to delete it somewhere else.
351 
352  If the index is less than 0 or greater than the size of the array, the
353  element will be added to the end of the array.
354  Otherwise, it will be inserted into the array, moving all the later elements
355  along to make room.
356 
357  Be careful not to add the same object to the array more than once,
358  as this will obviously cause deletion of dangling pointers.
359 
360  @param indexToInsertAt the index at which the new element should be inserted
361  @param newObject the new object to add to the array
362  @returns the new object that was added
363  @see add, addSorted, set
364  */
365  ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
366  {
367  return insert (indexToInsertAt, newObject.release());
368  }
369 
370  /** Inserts an array of values into this array at a given position.
371 
372  If the index is less than 0 or greater than the size of the array, the
373  new elements will be added to the end of the array.
374  Otherwise, they will be inserted into the array, moving all the later elements
375  along to make room.
376 
377  @param indexToInsertAt the index at which the first new element should be inserted
378  @param newObjects the new values to add to the array
379  @param numberOfElements how many items are in the array
380  @see insert, add, addSorted, set
381  */
382  void insertArray (int indexToInsertAt,
383  ObjectClass* const* newObjects,
384  int numberOfElements)
385  {
386  if (numberOfElements > 0)
387  {
388  const ScopedLockType lock (getLock());
389  values.insertArray (indexToInsertAt, newObjects, numberOfElements);
390  }
391  }
392 
393  /** Replaces an object in the array with a different one.
394 
395  If the index is less than zero, this method does nothing.
396  If the index is beyond the end of the array, the new object is added to the end of the array.
397 
398  Be careful not to add the same object to the array more than once,
399  as this will obviously cause deletion of dangling pointers.
400 
401  @param indexToChange the index whose value you want to change
402  @param newObject the new value to set for this index.
403  @param deleteOldElement whether to delete the object that's being replaced with the new one
404  @see add, insert, remove
405  */
406  ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
407  {
408  if (indexToChange >= 0)
409  {
410  std::unique_ptr<ObjectClass> toDelete;
411 
412  {
413  const ScopedLockType lock (getLock());
414 
415  if (indexToChange < values.size())
416  {
417  if (deleteOldElement)
418  {
419  toDelete.reset (values[indexToChange]);
420 
421  if (toDelete.get() == newObject)
422  toDelete.release();
423  }
424 
425  values[indexToChange] = newObject;
426  }
427  else
428  {
429  values.add (newObject);
430  }
431  }
432  }
433  else
434  {
435  jassertfalse; // you're trying to set an object at a negative index, which doesn't have
436  // any effect - but since the object is not being added, it may be leaking..
437  }
438 
439  return newObject;
440  }
441 
442  /** Replaces an object in the array with a different one.
443 
444  If the index is less than zero, this method does nothing.
445  If the index is beyond the end of the array, the new object is added to the end of the array.
446 
447  Be careful not to add the same object to the array more than once,
448  as this will obviously cause deletion of dangling pointers.
449 
450  @param indexToChange the index whose value you want to change
451  @param newObject the new value to set for this index.
452  @param deleteOldElement whether to delete the object that's being replaced with the new one
453  @see add, insert, remove
454  */
455  ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
456  {
457  return set (indexToChange, newObject.release(), deleteOldElement);
458  }
459 
460  /** Adds elements from another array to the end of this array.
461 
462  @param arrayToAddFrom the array from which to copy the elements
463  @param startIndex the first element of the other array to start copying from
464  @param numElementsToAdd how many elements to add from the other array. If this
465  value is negative or greater than the number of available elements,
466  all available elements will be copied.
467  @see add
468  */
469  template <class OtherArrayType>
470  void addArray (const OtherArrayType& arrayToAddFrom,
471  int startIndex = 0,
472  int numElementsToAdd = -1)
473  {
474  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
475  const ScopedLockType lock2 (getLock());
476  values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
477  }
478 
479  /** Adds elements from another array to the end of this array. */
480  template <typename OtherArrayType>
481  void addArray (const std::initializer_list<OtherArrayType>& items)
482  {
483  const ScopedLockType lock (getLock());
484  values.addArray (items);
485  }
486 
487  /** Adds copies of the elements in another array to the end of this array.
488 
489  The other array must be either an OwnedArray of a compatible type of object, or an Array
490  containing pointers to the same kind of object. The objects involved must provide
491  a copy constructor, and this will be used to create new copies of each element, and
492  add them to this array.
493 
494  @param arrayToAddFrom the array from which to copy the elements
495  @param startIndex the first element of the other array to start copying from
496  @param numElementsToAdd how many elements to add from the other array. If this
497  value is negative or greater than the number of available elements,
498  all available elements will be copied.
499  @see add
500  */
501  template <class OtherArrayType>
502  void addCopiesOf (const OtherArrayType& arrayToAddFrom,
503  int startIndex = 0,
504  int numElementsToAdd = -1)
505  {
506  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
507  const ScopedLockType lock2 (getLock());
508 
509  if (startIndex < 0)
510  {
511  jassertfalse;
512  startIndex = 0;
513  }
514 
515  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
516  numElementsToAdd = arrayToAddFrom.size() - startIndex;
517 
518  jassert (numElementsToAdd >= 0);
519  values.ensureAllocatedSize (values.size() + numElementsToAdd);
520 
521  while (--numElementsToAdd >= 0)
522  values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
523  }
524 
525  /** Inserts a new object into the array assuming that the array is sorted.
526 
527  This will use a comparator to find the position at which the new object
528  should go. If the array isn't sorted, the behaviour of this
529  method will be unpredictable.
530 
531  @param comparator the comparator to use to compare the elements - see the sort method
532  for details about this object's structure
533  @param newObject the new object to insert to the array
534  @returns the index at which the new object was added
535  @see add, sort, indexOfSorted
536  */
537  template <class ElementComparator>
538  int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept
539  {
540  // If you pass in an object with a static compareElements() method, this
541  // avoids getting warning messages about the parameter being unused
542  ignoreUnused (comparator);
543 
544  const ScopedLockType lock (getLock());
545  auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
546  insert (index, newObject);
547  return index;
548  }
549 
550  /** Finds the index of an object in the array, assuming that the array is sorted.
551 
552  This will use a comparator to do a binary-chop to find the index of the given
553  element, if it exists. If the array isn't sorted, the behaviour of this
554  method will be unpredictable.
555 
556  @param comparator the comparator to use to compare the elements - see the sort()
557  method for details about the form this object should take
558  @param objectToLookFor the object to search for
559  @returns the index of the element, or -1 if it's not found
560  @see addSorted, sort
561  */
562  template <typename ElementComparator>
563  int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept
564  {
565  // If you pass in an object with a static compareElements() method, this
566  // avoids getting warning messages about the parameter being unused
567  ignoreUnused (comparator);
568 
569  const ScopedLockType lock (getLock());
570  int s = 0, e = values.size();
571 
572  while (s < e)
573  {
574  if (comparator.compareElements (objectToLookFor, values[s]) == 0)
575  return s;
576 
577  auto halfway = (s + e) / 2;
578 
579  if (halfway == s)
580  break;
581 
582  if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
583  s = halfway;
584  else
585  e = halfway;
586  }
587 
588  return -1;
589  }
590 
591  //==============================================================================
592  /** Removes an object from the array.
593 
594  This will remove the object at a given index (optionally also
595  deleting it) and move back all the subsequent objects to close the gap.
596  If the index passed in is out-of-range, nothing will happen.
597 
598  @param indexToRemove the index of the element to remove
599  @param deleteObject whether to delete the object that is removed
600  @see removeObject, removeRange
601  */
602  void remove (int indexToRemove, bool deleteObject = true)
603  {
604  std::unique_ptr<ObjectClass> toDelete;
605 
606  {
607  const ScopedLockType lock (getLock());
608 
609  if (isPositiveAndBelow (indexToRemove, values.size()))
610  {
611  auto** e = values.begin() + indexToRemove;
612 
613  if (deleteObject)
614  toDelete.reset (*e);
615 
616  values.removeElements (indexToRemove, 1);
617  }
618  }
619 
620  if ((values.size() << 1) < values.capacity())
622  }
623 
624  /** Removes and returns an object from the array without deleting it.
625 
626  This will remove the object at a given index and return it, moving back all
627  the subsequent objects to close the gap. If the index passed in is out-of-range,
628  nothing will happen.
629 
630  @param indexToRemove the index of the element to remove
631  @see remove, removeObject, removeRange
632  */
633  ObjectClass* removeAndReturn (int indexToRemove)
634  {
635  ObjectClass* removedItem = nullptr;
636  const ScopedLockType lock (getLock());
637 
638  if (isPositiveAndBelow (indexToRemove, values.size()))
639  {
640  removedItem = values[indexToRemove];
641 
642  values.removeElements (indexToRemove, 1);
643 
644  if ((values.size() << 1) < values.capacity())
646  }
647 
648  return removedItem;
649  }
650 
651  /** Removes a specified object from the array.
652 
653  If the item isn't found, no action is taken.
654 
655  @param objectToRemove the object to try to remove
656  @param deleteObject whether to delete the object (if it's found)
657  @see remove, removeRange
658  */
659  void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
660  {
661  const ScopedLockType lock (getLock());
662 
663  for (int i = 0; i < values.size(); ++i)
664  {
665  if (objectToRemove == values[i])
666  {
667  remove (i, deleteObject);
668  break;
669  }
670  }
671  }
672 
673  /** Removes a range of objects from the array.
674 
675  This will remove a set of objects, starting from the given index,
676  and move any subsequent elements down to close the gap.
677 
678  If the range extends beyond the bounds of the array, it will
679  be safely clipped to the size of the array.
680 
681  @param startIndex the index of the first object to remove
682  @param numberToRemove how many objects should be removed
683  @param deleteObjects whether to delete the objects that get removed
684  @see remove, removeObject
685  */
686  void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
687  {
688  const ScopedLockType lock (getLock());
689  auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
690  startIndex = jlimit (0, values.size(), startIndex);
691  numberToRemove = endIndex - startIndex;
692 
693  if (numberToRemove > 0)
694  {
695  Array<ObjectClass*> objectsToDelete;
696 
697  if (deleteObjects)
698  objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
699 
700  values.removeElements (startIndex, numberToRemove);
701 
702  for (auto& o : objectsToDelete)
704 
705  if ((values.size() << 1) < values.capacity())
707  }
708  }
709 
710  /** Removes the last n objects from the array.
711 
712  @param howManyToRemove how many objects to remove from the end of the array
713  @param deleteObjects whether to also delete the objects that are removed
714  @see remove, removeObject, removeRange
715  */
716  void removeLast (int howManyToRemove = 1,
717  bool deleteObjects = true)
718  {
719  const ScopedLockType lock (getLock());
720 
721  if (howManyToRemove >= values.size())
722  clear (deleteObjects);
723  else
724  removeRange (values.size() - howManyToRemove, howManyToRemove, deleteObjects);
725  }
726 
727  /** Swaps a pair of objects in the array.
728 
729  If either of the indexes passed in is out-of-range, nothing will happen,
730  otherwise the two objects at these positions will be exchanged.
731  */
732  void swap (int index1, int index2) noexcept
733  {
734  const ScopedLockType lock (getLock());
735  values.swap (index1, index2);
736  }
737 
738  /** Moves one of the objects to a different position.
739 
740  This will move the object to a specified index, shuffling along
741  any intervening elements as required.
742 
743  So for example, if you have the array { 0, 1, 2, 3, 4, 5 } then calling
744  move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
745 
746  @param currentIndex the index of the object to be moved. If this isn't a
747  valid index, then nothing will be done
748  @param newIndex the index at which you'd like this object to end up. If this
749  is less than zero, it will be moved to the end of the array
750  */
751  void move (int currentIndex, int newIndex) noexcept
752  {
753  if (currentIndex != newIndex)
754  {
755  const ScopedLockType lock (getLock());
756  values.move (currentIndex, newIndex);
757  }
758  }
759 
760  /** This swaps the contents of this array with those of another array.
761 
762  If you need to exchange two arrays, this is vastly quicker than using copy-by-value
763  because it just swaps their internal pointers.
764  */
765  template <class OtherArrayType>
766  void swapWith (OtherArrayType& otherArray) noexcept
767  {
768  const ScopedLockType lock1 (getLock());
769  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
770  values.swapWith (otherArray.values);
771  }
772 
773  //==============================================================================
774  /** Reduces the amount of storage being used by the array.
775 
776  Arrays typically allocate slightly more storage than they need, and after
777  removing elements, they may have quite a lot of unused space allocated.
778  This method will reduce the amount of allocated storage to a minimum.
779  */
780  void minimiseStorageOverheads() noexcept
781  {
782  const ScopedLockType lock (getLock());
783  values.shrinkToNoMoreThan (values.size());
784  }
785 
786  /** Increases the array's internal storage to hold a minimum number of elements.
787 
788  Calling this before adding a large known number of elements means that
789  the array won't have to keep dynamically resizing itself as the elements
790  are added, and it'll therefore be more efficient.
791  */
792  void ensureStorageAllocated (int minNumElements) noexcept
793  {
794  const ScopedLockType lock (getLock());
795  values.ensureAllocatedSize (minNumElements);
796  }
797 
798  //==============================================================================
799  /** Sorts the elements in the array.
800 
801  This will use a comparator object to sort the elements into order. The object
802  passed must have a method of the form:
803  @code
804  int compareElements (ElementType* first, ElementType* second);
805  @endcode
806 
807  ..and this method must return:
808  - a value of < 0 if the first comes before the second
809  - a value of 0 if the two objects are equivalent
810  - a value of > 0 if the second comes before the first
811 
812  To improve performance, the compareElements() method can be declared as static or const.
813 
814  @param comparator the comparator to use for comparing elements.
815  @param retainOrderOfEquivalentItems if this is true, then items
816  which the comparator says are equivalent will be
817  kept in the order in which they currently appear
818  in the array. This is slower to perform, but may
819  be important in some cases. If it's false, a faster
820  algorithm is used, but equivalent elements may be
821  rearranged.
822  @see sortArray, indexOfSorted
823  */
824  template <class ElementComparator>
825  void sort (ElementComparator& comparator,
826  bool retainOrderOfEquivalentItems = false) noexcept
827  {
828  // If you pass in an object with a static compareElements() method, this
829  // avoids getting warning messages about the parameter being unused
830  ignoreUnused (comparator);
831 
832  const ScopedLockType lock (getLock());
833 
834  if (size() > 1)
835  sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
836  }
837 
838  //==============================================================================
839  /** Returns the CriticalSection that locks this array.
840  To lock, you can call getLock().enter() and getLock().exit(), or preferably use
841  an object of ScopedLockType as an RAII lock for it.
842  */
843  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
844 
845  /** Returns the type of scoped lock to use for locking this array */
846  using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
847 
848  //==============================================================================
849  #ifndef DOXYGEN
850  // Note that the swapWithArray method has been replaced by a more flexible templated version,
851  // and renamed "swapWith" to be more consistent with the names used in other classes.
852  JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
853  #endif
854 
855 private:
856  //==============================================================================
858 
859  void deleteAllObjects()
860  {
861  auto i = values.size();
862 
863  while (--i >= 0)
864  {
865  auto* e = values[i];
866  values.removeElements (i, 1);
868  }
869  }
870 
871  template <class OtherObjectClass, class OtherCriticalSection>
872  friend class OwnedArray;
873 
874  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
875 };
876 
877 } // namespace juce
878 
879 /** @}*/
ObjectClass * getFirst() const noexcept
Returns a pointer to the first object in the array.
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
Inserts an array of values into this array at a given position.
void minimiseStorageOverheads() noexcept
Reduces the amount of storage being used by the array.
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Adds copies of the elements in another array to the end of this array.
void clear(bool deleteObjects=true)
Clears the array, optionally deleting the objects inside it first.
ObjectClass ** data() noexcept
Returns a pointer to the first element in the array.
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Adds elements from an array to the end of this array.
Definition: juce_Array.h:587
void clearQuick(bool deleteObjects)
Clears the array, optionally deleting the objects inside it first.
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
OwnedArray(OwnedArray &&other) noexcept
Move constructor.
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object in the array, assuming that the array is sorted.
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Adds elements from another array to the end of this array.
~OwnedArray()
Deletes the array and also deletes any objects inside it.
ObjectClass * operator[](int index) const noexcept
Returns a pointer to the object at this index in the array.
ObjectClass * insert(int indexToInsertAt, std::unique_ptr< ObjectClass > newObject)
Inserts a new object into the array at the given index.
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Finds the index of an object which might be in the array.
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
void ensureStorageAllocated(int minNumElements) noexcept
Increases the array&#39;s internal storage to hold a minimum number of elements.
ObjectClass ** end() noexcept
Returns a pointer to the element which follows the last element in the array.
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
Removes the last n objects from the array.
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
Removes a range of objects from the array.
ObjectClass * add(std::unique_ptr< ObjectClass > newObject)
Appends a new object to the end of the array.
typename DummyCriticalSection ::ScopedLockType ScopedLockType
Returns the type of scoped lock to use for locking this array.
void addArray(const std::initializer_list< OtherArrayType > &items)
Adds elements from another array to the end of this array.
ObjectClass *const * begin() const noexcept
Returns a pointer to the first element in the array.
ObjectClass *const * data() const noexcept
Returns a pointer to the first element in the array.
ObjectClass ** getRawDataPointer() noexcept
Returns a pointer to the actual array data.
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
Removes a specified object from the array.
OwnedArray & operator=(OwnedArray &&other) noexcept
Move assignment operator.
ObjectClass *const * end() const noexcept
Returns a pointer to the element which follows the last element in the array.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
int size() const noexcept
Returns the number of items currently in the array.
ObjectClass * getUnchecked(int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Inserts a new object into the array assuming that the array is sorted.
Used by container classes as an indirect way to delete an object of a particular type.
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Inserts a new object into the array at the given index.
OwnedArray(const std::initializer_list< ObjectClass *> &items)
Creates an array from a list of objects.
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Sorts the elements in the array.
ObjectClass * add(ObjectClass *newObject)
Appends a new object to the end of the array.
void swap(int index1, int index2) noexcept
Swaps a pair of objects in the array.
An array designed for holding objects.
OwnedArray(OwnedArray< OtherObjectClass, OtherCriticalSection > &&other) noexcept
Converting move constructor.
ObjectClass ** begin() noexcept
Returns a pointer to the first element in the array.
OwnedArray()=default
Creates an empty array.
ObjectClass * getLast() const noexcept
Returns a pointer to the last object in the array.
bool contains(const ObjectClass *objectToLookFor) const noexcept
Returns true if the array contains a specified object.
ObjectClass * removeAndReturn(int indexToRemove)
Removes and returns an object from the array without deleting it.
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
void move(int currentIndex, int newIndex) noexcept
Moves one of the objects to a different position.