openshot-audio  0.1.6
juce_OwnedArray.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the juce_core module of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission to use, copy, modify, and/or distribute this software for any purpose with
8  or without fee is hereby granted, provided that the above copyright notice and this
9  permission notice appear in all copies.
10 
11  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
12  TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
13  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
15  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 
18  ------------------------------------------------------------------------------
19 
20  NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
21  All other JUCE modules are covered by a dual GPL/commercial license, so if you are
22  using any other modules, be sure to check that you also comply with their license.
23 
24  For more details, visit www.juce.com
25 
26  ==============================================================================
27 */
28 
29 #ifndef JUCE_OWNEDARRAY_H_INCLUDED
30 #define JUCE_OWNEDARRAY_H_INCLUDED
31 
32 
33 //==============================================================================
52 template <class ObjectClass,
53  class TypeOfCriticalSectionToUse = DummyCriticalSection>
54 
56 {
57 public:
58  //==============================================================================
61  : numUsed (0)
62  {
63  }
64 
71  {
73  }
74 
75  #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
77  : data (static_cast <ArrayAllocationBase <ObjectClass*, TypeOfCriticalSectionToUse>&&> (other.data)),
78  numUsed (other.numUsed)
79  {
80  other.numUsed = 0;
81  }
82 
83  OwnedArray& operator= (OwnedArray&& other) noexcept
84  {
85  const ScopedLockType lock (getLock());
87 
89  numUsed = other.numUsed;
90  other.numUsed = 0;
91  return *this;
92  }
93  #endif
94 
95  //==============================================================================
97  void clear (bool deleteObjects = true)
98  {
99  const ScopedLockType lock (getLock());
100 
101  if (deleteObjects)
103 
104  data.setAllocatedSize (0);
105  numUsed = 0;
106  }
107 
108  //==============================================================================
110  void clearQuick (bool deleteObjects)
111  {
112  const ScopedLockType lock (getLock());
113 
114  if (deleteObjects)
116 
117  numUsed = 0;
118  }
119 
120  //==============================================================================
124  inline int size() const noexcept
125  {
126  return numUsed;
127  }
128 
137  inline ObjectClass* operator[] (const int index) const noexcept
138  {
139  const ScopedLockType lock (getLock());
140  if (isPositiveAndBelow (index, numUsed))
141  {
142  jassert (data.elements != nullptr);
143  return data.elements [index];
144  }
145 
146  return nullptr;
147  }
148 
154  inline ObjectClass* getUnchecked (const int index) const noexcept
155  {
156  const ScopedLockType lock (getLock());
157  jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
158  return data.elements [index];
159  }
160 
166  inline ObjectClass* getFirst() const noexcept
167  {
168  const ScopedLockType lock (getLock());
169 
170  if (numUsed > 0)
171  {
172  jassert (data.elements != nullptr);
173  return data.elements [0];
174  }
175 
176  return nullptr;
177  }
178 
184  inline ObjectClass* getLast() const noexcept
185  {
186  const ScopedLockType lock (getLock());
187 
188  if (numUsed > 0)
189  {
190  jassert (data.elements != nullptr);
191  return data.elements [numUsed - 1];
192  }
193 
194  return nullptr;
195  }
196 
201  inline ObjectClass** getRawDataPointer() noexcept
202  {
203  return data.elements;
204  }
205 
206  //==============================================================================
210  inline ObjectClass** begin() const noexcept
211  {
212  return data.elements;
213  }
214 
218  inline ObjectClass** end() const noexcept
219  {
220  #if JUCE_DEBUG
221  if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
222  return data.elements;
223  #endif
224 
225  return data.elements + numUsed;
226  }
227 
228  //==============================================================================
234  int indexOf (const ObjectClass* objectToLookFor) const noexcept
235  {
236  const ScopedLockType lock (getLock());
237  ObjectClass* const* e = data.elements.getData();
238  ObjectClass* const* const end_ = e + numUsed;
239 
240  for (; e != end_; ++e)
241  if (objectToLookFor == *e)
242  return static_cast <int> (e - data.elements.getData());
243 
244  return -1;
245  }
246 
252  bool contains (const ObjectClass* objectToLookFor) const noexcept
253  {
254  const ScopedLockType lock (getLock());
255  ObjectClass* const* e = data.elements.getData();
256  ObjectClass* const* const end_ = e + numUsed;
257 
258  for (; e != end_; ++e)
259  if (objectToLookFor == *e)
260  return true;
261 
262  return false;
263  }
264 
265  //==============================================================================
278  ObjectClass* add (ObjectClass* newObject) noexcept
279  {
280  const ScopedLockType lock (getLock());
281  data.ensureAllocatedSize (numUsed + 1);
282  jassert (data.elements != nullptr);
283  data.elements [numUsed++] = newObject;
284  return newObject;
285  }
286 
305  ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject) noexcept
306  {
307  if (indexToInsertAt < 0)
308  return add (newObject);
309 
310  const ScopedLockType lock (getLock());
311 
312  if (indexToInsertAt > numUsed)
313  indexToInsertAt = numUsed;
314 
315  data.ensureAllocatedSize (numUsed + 1);
316  jassert (data.elements != nullptr);
317 
318  ObjectClass** const e = data.elements + indexToInsertAt;
319  const int numToMove = numUsed - indexToInsertAt;
320 
321  if (numToMove > 0)
322  memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
323 
324  *e = newObject;
325  ++numUsed;
326  return newObject;
327  }
328 
341  void insertArray (int indexToInsertAt,
342  ObjectClass* const* newObjects,
343  int numberOfElements)
344  {
345  if (numberOfElements > 0)
346  {
347  const ScopedLockType lock (getLock());
348  data.ensureAllocatedSize (numUsed + numberOfElements);
349  ObjectClass** insertPos = data.elements;
350 
351  if (isPositiveAndBelow (indexToInsertAt, numUsed))
352  {
353  insertPos += indexToInsertAt;
354  const size_t numberToMove = (size_t) (numUsed - indexToInsertAt);
355  memmove (insertPos + numberOfElements, insertPos, numberToMove * sizeof (ObjectClass*));
356  }
357  else
358  {
359  insertPos += numUsed;
360  }
361 
362  numUsed += numberOfElements;
363 
364  while (--numberOfElements >= 0)
365  *insertPos++ = *newObjects++;
366  }
367  }
368 
377  ObjectClass* addIfNotAlreadyThere (ObjectClass* newObject) noexcept
378  {
379  const ScopedLockType lock (getLock());
380 
381  if (! contains (newObject))
382  add (newObject);
383 
384  return newObject;
385  }
386 
400  ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
401  {
402  if (indexToChange >= 0)
403  {
405 
406  {
407  const ScopedLockType lock (getLock());
408 
409  if (indexToChange < numUsed)
410  {
411  if (deleteOldElement)
412  {
413  toDelete = data.elements [indexToChange];
414 
415  if (toDelete == newObject)
416  toDelete.release();
417  }
418 
419  data.elements [indexToChange] = newObject;
420  }
421  else
422  {
423  data.ensureAllocatedSize (numUsed + 1);
424  data.elements [numUsed++] = newObject;
425  }
426  }
427  }
428  else
429  {
430  jassertfalse; // you're trying to set an object at a negative index, which doesn't have
431  // any effect - but since the object is not being added, it may be leaking..
432  }
433 
434  return newObject;
435  }
436 
446  template <class OtherArrayType>
447  void addArray (const OtherArrayType& arrayToAddFrom,
448  int startIndex = 0,
449  int numElementsToAdd = -1)
450  {
451  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
452  const ScopedLockType lock2 (getLock());
453 
454  if (startIndex < 0)
455  {
456  jassertfalse;
457  startIndex = 0;
458  }
459 
460  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
461  numElementsToAdd = arrayToAddFrom.size() - startIndex;
462 
463  data.ensureAllocatedSize (numUsed + numElementsToAdd);
464  jassert (numElementsToAdd <= 0 || data.elements != nullptr);
465 
466  while (--numElementsToAdd >= 0)
467  {
468  data.elements [numUsed] = arrayToAddFrom.getUnchecked (startIndex++);
469  ++numUsed;
470  }
471  }
472 
487  template <class OtherArrayType>
488  void addCopiesOf (const OtherArrayType& arrayToAddFrom,
489  int startIndex = 0,
490  int numElementsToAdd = -1)
491  {
492  const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
493  const ScopedLockType lock2 (getLock());
494 
495  if (startIndex < 0)
496  {
497  jassertfalse;
498  startIndex = 0;
499  }
500 
501  if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
502  numElementsToAdd = arrayToAddFrom.size() - startIndex;
503 
504  data.ensureAllocatedSize (numUsed + numElementsToAdd);
505  jassert (numElementsToAdd <= 0 || data.elements != nullptr);
506 
507  while (--numElementsToAdd >= 0)
508  data.elements [numUsed++] = createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++));
509  }
510 
523  template <class ElementComparator>
524  int addSorted (ElementComparator& comparator, ObjectClass* const newObject) noexcept
525  {
526  (void) comparator; // if you pass in an object with a static compareElements() method, this
527  // avoids getting warning messages about the parameter being unused
528  const ScopedLockType lock (getLock());
529  const int index = findInsertIndexInSortedArray (comparator, data.elements.getData(), newObject, 0, numUsed);
530  insert (index, newObject);
531  return index;
532  }
533 
546  template <typename ElementComparator>
547  int indexOfSorted (ElementComparator& comparator, const ObjectClass* const objectToLookFor) const noexcept
548  {
549  (void) comparator;
550  const ScopedLockType lock (getLock());
551  int s = 0, e = numUsed;
552 
553  while (s < e)
554  {
555  if (comparator.compareElements (objectToLookFor, data.elements [s]) == 0)
556  return s;
557 
558  const int halfway = (s + e) / 2;
559  if (halfway == s)
560  break;
561 
562  if (comparator.compareElements (objectToLookFor, data.elements [halfway]) >= 0)
563  s = halfway;
564  else
565  e = halfway;
566  }
567 
568  return -1;
569  }
570 
571  //==============================================================================
582  void remove (int indexToRemove, bool deleteObject = true)
583  {
585 
586  {
587  const ScopedLockType lock (getLock());
588 
589  if (isPositiveAndBelow (indexToRemove, numUsed))
590  {
591  ObjectClass** const e = data.elements + indexToRemove;
592 
593  if (deleteObject)
594  toDelete = *e;
595 
596  --numUsed;
597  const int numToShift = numUsed - indexToRemove;
598 
599  if (numToShift > 0)
600  memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numToShift);
601  }
602  }
603 
604  if ((numUsed << 1) < data.numAllocated)
606  }
607 
617  ObjectClass* removeAndReturn (int indexToRemove)
618  {
619  ObjectClass* removedItem = nullptr;
620  const ScopedLockType lock (getLock());
621 
622  if (isPositiveAndBelow (indexToRemove, numUsed))
623  {
624  ObjectClass** const e = data.elements + indexToRemove;
625  removedItem = *e;
626 
627  --numUsed;
628  const int numToShift = numUsed - indexToRemove;
629 
630  if (numToShift > 0)
631  memmove (e, e + 1, sizeof (ObjectClass*) * (size_t) numToShift);
632 
633  if ((numUsed << 1) < data.numAllocated)
635  }
636 
637  return removedItem;
638  }
639 
648  void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
649  {
650  const ScopedLockType lock (getLock());
651  ObjectClass** const e = data.elements.getData();
652 
653  for (int i = 0; i < numUsed; ++i)
654  {
655  if (objectToRemove == e[i])
656  {
657  remove (i, deleteObject);
658  break;
659  }
660  }
661  }
662 
676  void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
677  {
678  const ScopedLockType lock (getLock());
679  const int endIndex = jlimit (0, numUsed, startIndex + numberToRemove);
680  startIndex = jlimit (0, numUsed, startIndex);
681 
682  if (endIndex > startIndex)
683  {
684  if (deleteObjects)
685  {
686  for (int i = startIndex; i < endIndex; ++i)
687  {
689  data.elements [i] = nullptr; // (in case one of the destructors accesses this array and hits a dangling pointer)
690  }
691  }
692 
693  const int rangeSize = endIndex - startIndex;
694  ObjectClass** e = data.elements + startIndex;
695  int numToShift = numUsed - endIndex;
696  numUsed -= rangeSize;
697 
698  while (--numToShift >= 0)
699  {
700  *e = e [rangeSize];
701  ++e;
702  }
703 
704  if ((numUsed << 1) < data.numAllocated)
706  }
707  }
708 
715  void removeLast (int howManyToRemove = 1,
716  bool deleteObjects = true)
717  {
718  const ScopedLockType lock (getLock());
719 
720  if (howManyToRemove >= numUsed)
721  clear (deleteObjects);
722  else
723  removeRange (numUsed - howManyToRemove, howManyToRemove, deleteObjects);
724  }
725 
731  void swap (int index1,
732  int index2) noexcept
733  {
734  const ScopedLockType lock (getLock());
735 
736  if (isPositiveAndBelow (index1, numUsed)
737  && isPositiveAndBelow (index2, numUsed))
738  {
739  std::swap (data.elements [index1],
740  data.elements [index2]);
741  }
742  }
743 
757  void move (int currentIndex, int newIndex) noexcept
758  {
759  if (currentIndex != newIndex)
760  {
761  const ScopedLockType lock (getLock());
762 
763  if (isPositiveAndBelow (currentIndex, numUsed))
764  {
765  if (! isPositiveAndBelow (newIndex, numUsed))
766  newIndex = numUsed - 1;
767 
768  ObjectClass* const value = data.elements [currentIndex];
769 
770  if (newIndex > currentIndex)
771  {
772  memmove (data.elements + currentIndex,
773  data.elements + currentIndex + 1,
774  sizeof (ObjectClass*) * (size_t) (newIndex - currentIndex));
775  }
776  else
777  {
778  memmove (data.elements + newIndex + 1,
779  data.elements + newIndex,
780  sizeof (ObjectClass*) * (size_t) (currentIndex - newIndex));
781  }
782 
783  data.elements [newIndex] = value;
784  }
785  }
786  }
787 
793  template <class OtherArrayType>
794  void swapWith (OtherArrayType& otherArray) noexcept
795  {
796  const ScopedLockType lock1 (getLock());
797  const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
798  data.swapWith (otherArray.data);
799  std::swap (numUsed, otherArray.numUsed);
800  }
801 
802  //==============================================================================
809  void minimiseStorageOverheads() noexcept
810  {
811  const ScopedLockType lock (getLock());
812  data.shrinkToNoMoreThan (numUsed);
813  }
814 
821  void ensureStorageAllocated (const int minNumElements) noexcept
822  {
823  const ScopedLockType lock (getLock());
824  data.ensureAllocatedSize (minNumElements);
825  }
826 
827  //==============================================================================
853  template <class ElementComparator>
854  void sort (ElementComparator& comparator,
855  bool retainOrderOfEquivalentItems = false) const noexcept
856  {
857  (void) comparator; // if you pass in an object with a static compareElements() method, this
858  // avoids getting warning messages about the parameter being unused
859 
860  const ScopedLockType lock (getLock());
861  sortArray (comparator, data.elements.getData(), 0, size() - 1, retainOrderOfEquivalentItems);
862  }
863 
864  //==============================================================================
869  inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return data; }
870 
872  typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
873 
874 
875  //==============================================================================
876  #ifndef DOXYGEN
877  // Note that the swapWithArray method has been replaced by a more flexible templated version,
878  // and renamed "swapWith" to be more consistent with the names used in other classes.
879  JUCE_DEPRECATED_WITH_BODY (void swapWithArray (OwnedArray& other) noexcept, { swapWith (other); })
880  #endif
881 
882 private:
883  //==============================================================================
885  int numUsed;
886 
888  {
889  while (numUsed > 0)
890  ContainerDeletePolicy<ObjectClass>::destroy (data.elements [--numUsed]);
891  }
892 
894 };
895 
896 
897 #endif // JUCE_OWNEDARRAY_H_INCLUDED
int indexOfSorted(ElementComparator &comparator, const ObjectClass *const objectToLookFor) const noexcept
Definition: juce_OwnedArray.h:547
ObjectType * release() noexcept
Definition: juce_ScopedPointer.h:179
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) const noexcept
Definition: juce_OwnedArray.h:854
void swapWith(OtherArrayType &otherArray) noexcept
Definition: juce_OwnedArray.h:794
ObjectClass * getLast() const noexcept
Definition: juce_OwnedArray.h:184
ObjectClass * getUnchecked(const int index) const noexcept
Definition: juce_OwnedArray.h:154
~OwnedArray()
Definition: juce_OwnedArray.h:70
#define noexcept
Definition: juce_CompilerSupport.h:141
int size() const noexcept
Definition: juce_OwnedArray.h:124
void deleteAllObjects()
Definition: juce_OwnedArray.h:887
OwnedArray() noexcept
Definition: juce_OwnedArray.h:60
bool isPositiveAndBelow(Type valueToTest, Type upperLimit) noexcept
Definition: juce_core.h:238
void swap(int index1, int index2) noexcept
Definition: juce_OwnedArray.h:731
Definition: juce_ArrayAllocationBase.h:46
void move(int currentIndex, int newIndex) noexcept
Definition: juce_OwnedArray.h:757
void clear(bool deleteObjects=true)
Definition: juce_OwnedArray.h:97
#define jassertfalse
Definition: juce_PlatformDefs.h:141
#define const
TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Definition: juce_OwnedArray.h:872
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Definition: juce_OwnedArray.h:488
ObjectClass * getFirst() const noexcept
Definition: juce_OwnedArray.h:166
void ensureStorageAllocated(const int minNumElements) noexcept
Definition: juce_OwnedArray.h:821
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Definition: juce_OwnedArray.h:234
ObjectClass * set(int indexToChange, ObjectClass *newObject, bool deleteOldElement=true)
Definition: juce_OwnedArray.h:400
void clearQuick(bool deleteObjects)
Definition: juce_OwnedArray.h:110
Definition: juce_ScopedPointer.h:70
Type * createCopyIfNotNull(const Type *objectToCopy)
Definition: juce_Memory.h:65
const TypeOfCriticalSectionToUse & getLock() const noexcept
Definition: juce_OwnedArray.h:869
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition: juce_MathsFunctions.h:220
#define jassert(a)
Definition: juce_PlatformDefs.h:146
void
Definition: juce_PNGLoader.cpp:1173
Definition: juce_OwnedArray.h:55
JUCE_DEPRECATED_WITH_BODY(void swapWithArray(OwnedArray &other) noexcept,{swapWith(other);}) private int numUsed
Definition: juce_OwnedArray.h:879
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
Definition: juce_PlatformDefs.h:198
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
Definition: juce_OwnedArray.h:676
void minimiseStorageOverheads() noexcept
Definition: juce_OwnedArray.h:809
ObjectClass * addIfNotAlreadyThere(ObjectClass *newObject) noexcept
Definition: juce_OwnedArray.h:377
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Definition: juce_OwnedArray.h:447
JSAMPIMAGE data
Definition: jpeglib.h:945
ObjectClass * add(ObjectClass *newObject) noexcept
Definition: juce_OwnedArray.h:278
int addSorted(ElementComparator &comparator, ObjectClass *const newObject) noexcept
Definition: juce_OwnedArray.h:524
Definition: juce_CriticalSection.h:136
ObjectClass ** getRawDataPointer() noexcept
Definition: juce_OwnedArray.h:201
ObjectClass ** begin() const noexcept
Definition: juce_OwnedArray.h:210
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
Definition: juce_OwnedArray.h:341
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject) noexcept
Definition: juce_OwnedArray.h:305
bool contains(const ObjectClass *objectToLookFor) const noexcept
Definition: juce_OwnedArray.h:252
ObjectClass * removeAndReturn(int indexToRemove)
Definition: juce_OwnedArray.h:617
#define JUCE_DEPRECATED_WITH_BODY(functionDef, body)
Definition: juce_PlatformDefs.h:320
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
Definition: juce_OwnedArray.h:715
ObjectClass * operator[](const int index) const noexcept
Definition: juce_OwnedArray.h:137
ObjectClass ** end() const noexcept
Definition: juce_OwnedArray.h:218
static void destroy(ObjectType *object)
Definition: juce_ContainerDeletePolicy.h:46
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
Definition: juce_OwnedArray.h:648