Loading...
Searching...
No Matches
juce_OwnedArray.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
template <class ObjectClass,
class TypeOfCriticalSectionToUse = DummyCriticalSection>
class OwnedArray
{
public:
//==============================================================================
OwnedArray() = default;
~OwnedArray()
{
deleteAllObjects();
}
OwnedArray (OwnedArray&& other) noexcept
: values (std::move (other.values))
{
}
OwnedArray (const std::initializer_list<ObjectClass*>& items)
{
addArray (items);
}
OwnedArray& operator= (OwnedArray&& other) noexcept
{
const ScopedLockType lock (getLock());
deleteAllObjects();
values = std::move (other.values);
return *this;
}
template <class OtherObjectClass, class OtherCriticalSection>
OwnedArray (OwnedArray<OtherObjectClass, OtherCriticalSection>&& other) noexcept
: values (std::move (other.values))
{
}
template <class OtherObjectClass, class OtherCriticalSection>
OwnedArray& operator= (OwnedArray<OtherObjectClass, OtherCriticalSection>&& other) noexcept
{
const ScopedLockType lock (getLock());
deleteAllObjects();
values = std::move (other.values);
return *this;
}
//==============================================================================
void clear (bool deleteObjects = true)
{
const ScopedLockType lock (getLock());
clearQuick (deleteObjects);
values.setAllocatedSize (0);
}
//==============================================================================
void clearQuick (bool deleteObjects)
{
const ScopedLockType lock (getLock());
if (deleteObjects)
deleteAllObjects();
else
values.clear();
}
//==============================================================================
inline int size() const noexcept
{
return values.size();
}
inline bool isEmpty() const noexcept
{
return size() == 0;
}
inline ObjectClass* operator[] (int index) const noexcept
{
const ScopedLockType lock (getLock());
return values.getValueWithDefault (index);
}
inline ObjectClass* getUnchecked (int index) const noexcept
{
const ScopedLockType lock (getLock());
return values[index];
}
inline ObjectClass* getFirst() const noexcept
{
const ScopedLockType lock (getLock());
return values.getFirst();
}
inline ObjectClass* getLast() const noexcept
{
const ScopedLockType lock (getLock());
return values.getLast();
}
inline ObjectClass** getRawDataPointer() noexcept
{
return values.begin();
}
//==============================================================================
inline ObjectClass** begin() noexcept
{
return values.begin();
}
inline ObjectClass* const* begin() const noexcept
{
return values.begin();
}
inline ObjectClass** end() noexcept
{
return values.end();
}
inline ObjectClass* const* end() const noexcept
{
return values.end();
}
inline ObjectClass** data() noexcept
{
return begin();
}
inline ObjectClass* const* data() const noexcept
{
return begin();
}
//==============================================================================
int indexOf (const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
auto* e = values.begin();
for (; e != values.end(); ++e)
if (objectToLookFor == *e)
return static_cast<int> (e - values.begin());
return -1;
}
bool contains (const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
auto* e = values.begin();
for (; e != values.end(); ++e)
if (objectToLookFor == *e)
return true;
return false;
}
//==============================================================================
ObjectClass* add (ObjectClass* newObject)
{
const ScopedLockType lock (getLock());
values.add (newObject);
return newObject;
}
ObjectClass* add (std::unique_ptr<ObjectClass> newObject)
{
return add (newObject.release());
}
ObjectClass* insert (int indexToInsertAt, ObjectClass* newObject)
{
const ScopedLockType lock (getLock());
values.insert (indexToInsertAt, newObject, 1);
return newObject;
}
ObjectClass* insert (int indexToInsertAt, std::unique_ptr<ObjectClass> newObject)
{
return insert (indexToInsertAt, newObject.release());
}
void insertArray (int indexToInsertAt,
ObjectClass* const* newObjects,
int numberOfElements)
{
if (numberOfElements > 0)
{
const ScopedLockType lock (getLock());
values.insertArray (indexToInsertAt, newObjects, numberOfElements);
}
}
ObjectClass* set (int indexToChange, ObjectClass* newObject, bool deleteOldElement = true)
{
if (indexToChange >= 0)
{
std::unique_ptr<ObjectClass> toDelete;
{
const ScopedLockType lock (getLock());
if (indexToChange < values.size())
{
if (deleteOldElement)
{
toDelete.reset (values[indexToChange]);
if (toDelete.get() == newObject)
toDelete.release();
}
values[indexToChange] = newObject;
}
else
{
values.add (newObject);
}
}
}
else
{
jassertfalse; // you're trying to set an object at a negative index, which doesn't have
// any effect - but since the object is not being added, it may be leaking..
}
return newObject;
}
ObjectClass* set (int indexToChange, std::unique_ptr<ObjectClass> newObject, bool deleteOldElement = true)
{
return set (indexToChange, newObject.release(), deleteOldElement);
}
template <class OtherArrayType>
void addArray (const OtherArrayType& arrayToAddFrom,
int startIndex = 0,
int numElementsToAdd = -1)
{
const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
const ScopedLockType lock2 (getLock());
values.addArray (arrayToAddFrom, startIndex, numElementsToAdd);
}
template <typename OtherArrayType>
void addArray (const std::initializer_list<OtherArrayType>& items)
{
const ScopedLockType lock (getLock());
values.addArray (items);
}
template <class OtherArrayType>
void addCopiesOf (const OtherArrayType& arrayToAddFrom,
int startIndex = 0,
int numElementsToAdd = -1)
{
const typename OtherArrayType::ScopedLockType lock1 (arrayToAddFrom.getLock());
const ScopedLockType lock2 (getLock());
if (startIndex < 0)
{
jassertfalse;
startIndex = 0;
}
if (numElementsToAdd < 0 || startIndex + numElementsToAdd > arrayToAddFrom.size())
numElementsToAdd = arrayToAddFrom.size() - startIndex;
jassert (numElementsToAdd >= 0);
values.ensureAllocatedSize (values.size() + numElementsToAdd);
while (--numElementsToAdd >= 0)
values.add (createCopyIfNotNull (arrayToAddFrom.getUnchecked (startIndex++)));
}
template <class ElementComparator>
int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept;
template <typename ElementComparator>
int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;
//==============================================================================
void remove (int indexToRemove, bool deleteObject = true)
{
std::unique_ptr<ObjectClass> toDelete;
{
const ScopedLockType lock (getLock());
if (isPositiveAndBelow (indexToRemove, values.size()))
{
auto** e = values.begin() + indexToRemove;
if (deleteObject)
toDelete.reset (*e);
values.removeElements (indexToRemove, 1);
}
}
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
ObjectClass* removeAndReturn (int indexToRemove)
{
ObjectClass* removedItem = nullptr;
const ScopedLockType lock (getLock());
if (isPositiveAndBelow (indexToRemove, values.size()))
{
removedItem = values[indexToRemove];
values.removeElements (indexToRemove, 1);
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
return removedItem;
}
void removeObject (const ObjectClass* objectToRemove, bool deleteObject = true)
{
const ScopedLockType lock (getLock());
for (int i = 0; i < values.size(); ++i)
{
if (objectToRemove == values[i])
{
remove (i, deleteObject);
break;
}
}
}
void removeRange (int startIndex, int numberToRemove, bool deleteObjects = true)
{
const ScopedLockType lock (getLock());
auto endIndex = jlimit (0, values.size(), startIndex + numberToRemove);
startIndex = jlimit (0, values.size(), startIndex);
numberToRemove = endIndex - startIndex;
if (numberToRemove > 0)
{
Array<ObjectClass*> objectsToDelete;
if (deleteObjects)
objectsToDelete.addArray (values.begin() + startIndex, numberToRemove);
values.removeElements (startIndex, numberToRemove);
for (auto& o : objectsToDelete)
ContainerDeletePolicy<ObjectClass>::destroy (o);
if ((values.size() << 1) < values.capacity())
minimiseStorageOverheads();
}
}
void removeLast (int howManyToRemove = 1,
bool deleteObjects = true)
{
const ScopedLockType lock (getLock());
if (howManyToRemove >= values.size())
clear (deleteObjects);
else
removeRange (values.size() - howManyToRemove, howManyToRemove, deleteObjects);
}
void swap (int index1, int index2) noexcept
{
const ScopedLockType lock (getLock());
values.swap (index1, index2);
}
void move (int currentIndex, int newIndex) noexcept
{
if (currentIndex != newIndex)
{
const ScopedLockType lock (getLock());
values.move (currentIndex, newIndex);
}
}
template <class OtherArrayType>
void swapWith (OtherArrayType& otherArray) noexcept
{
const ScopedLockType lock1 (getLock());
const typename OtherArrayType::ScopedLockType lock2 (otherArray.getLock());
values.swapWith (otherArray.values);
}
//==============================================================================
void minimiseStorageOverheads() noexcept
{
const ScopedLockType lock (getLock());
values.shrinkToNoMoreThan (values.size());
}
void ensureStorageAllocated (int minNumElements) noexcept
{
const ScopedLockType lock (getLock());
values.ensureAllocatedSize (minNumElements);
}
//==============================================================================
template <class ElementComparator>
void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;
//==============================================================================
inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return values; }
using ScopedLockType = typename TypeOfCriticalSectionToUse::ScopedLockType;
//==============================================================================
#ifndef DOXYGEN
[[deprecated ("This method has been replaced by a more flexible templated version and renamed "
"to swapWith to be more consistent with the names used in other classes.")]]
void swapWithArray (OwnedArray& other) noexcept { swapWith (other); }
#endif
private:
//==============================================================================
ArrayBase <ObjectClass*, TypeOfCriticalSectionToUse> values;
void deleteAllObjects()
{
auto i = values.size();
while (--i >= 0)
{
auto* e = values[i];
values.removeElements (i, 1);
ContainerDeletePolicy<ObjectClass>::destroy (e);
}
}
template <class OtherObjectClass, class OtherCriticalSection>
friend class OwnedArray;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)
};
//==============================================================================
template <class ObjectClass, class TypeOfCriticalSectionToUse>
template <class ElementComparator>
int OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::addSorted (
[[maybe_unused]] ElementComparator& comparator,
ObjectClass* newObject) noexcept
{
const ScopedLockType lock (getLock());
auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());
insert (index, newObject);
return index;
}
template <class ObjectClass, class TypeOfCriticalSectionToUse>
template <typename ElementComparator>
int OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::indexOfSorted (
[[maybe_unused]] ElementComparator& comparator,
const ObjectClass* objectToLookFor) const noexcept
{
const ScopedLockType lock (getLock());
int s = 0, e = values.size();
while (s < e)
{
if (comparator.compareElements (objectToLookFor, values[s]) == 0)
return s;
auto halfway = (s + e) / 2;
if (halfway == s)
break;
if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)
s = halfway;
else
e = halfway;
}
return -1;
}
template <class ObjectClass, class TypeOfCriticalSectionToUse>
template <typename ElementComparator>
void OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::sort (
[[maybe_unused]] ElementComparator& comparator,
bool retainOrderOfEquivalentItems) noexcept
{
const ScopedLockType lock (getLock());
if (size() > 1)
sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);
}
} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::addArray
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
juce::DummyCriticalSection
Definition juce_CriticalSection.h:134
juce::OwnedArray::data
ObjectClass *const * data() const noexcept
Definition juce_OwnedArray.h:240
juce::OwnedArray::size
int size() const noexcept
Definition juce_OwnedArray.h:129
juce::OwnedArray::getUnchecked
ObjectClass * getUnchecked(int index) const noexcept
Definition juce_OwnedArray.h:159
juce::OwnedArray::set
ObjectClass * set(int indexToChange, ObjectClass *newObject, bool deleteOldElement=true)
Definition juce_OwnedArray.h:401
juce::OwnedArray::removeAndReturn
ObjectClass * removeAndReturn(int indexToRemove)
Definition juce_OwnedArray.h:592
juce::OwnedArray::add
ObjectClass * add(std::unique_ptr< ObjectClass > newObject)
Definition juce_OwnedArray.h:312
juce::OwnedArray::set
ObjectClass * set(int indexToChange, std::unique_ptr< ObjectClass > newObject, bool deleteOldElement=true)
Definition juce_OwnedArray.h:450
juce::OwnedArray::addCopiesOf
void addCopiesOf(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Definition juce_OwnedArray.h:497
juce::OwnedArray::addArray
void addArray(const OtherArrayType &arrayToAddFrom, int startIndex=0, int numElementsToAdd=-1)
Definition juce_OwnedArray.h:465
juce::OwnedArray::isEmpty
bool isEmpty() const noexcept
Definition juce_OwnedArray.h:135
juce::OwnedArray::swapWith
void swapWith(OtherArrayType &otherArray) noexcept
Definition juce_OwnedArray.h:725
juce::OwnedArray::remove
void remove(int indexToRemove, bool deleteObject=true)
Definition juce_OwnedArray.h:561
juce::OwnedArray::ScopedLockType
typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType
Definition juce_OwnedArray.h:794
juce::OwnedArray::ensureStorageAllocated
void ensureStorageAllocated(int minNumElements) noexcept
Definition juce_OwnedArray.h:751
juce::OwnedArray::getFirst
ObjectClass * getFirst() const noexcept
Definition juce_OwnedArray.h:170
juce::OwnedArray::minimiseStorageOverheads
void minimiseStorageOverheads() noexcept
Definition juce_OwnedArray.h:739
juce::OwnedArray::clear
void clear(bool deleteObjects=true)
Definition juce_OwnedArray.h:106
juce::OwnedArray::removeLast
void removeLast(int howManyToRemove=1, bool deleteObjects=true)
Definition juce_OwnedArray.h:675
juce::OwnedArray::indexOf
int indexOf(const ObjectClass *objectToLookFor) const noexcept
Definition juce_OwnedArray.h:251
juce::OwnedArray::add
ObjectClass * add(ObjectClass *newObject)
Definition juce_OwnedArray.h:293
juce::OwnedArray::begin
ObjectClass ** begin() noexcept
Definition juce_OwnedArray.h:200
juce::OwnedArray::OwnedArray
OwnedArray(OwnedArray< OtherObjectClass, OtherCriticalSection > &&other) noexcept
Definition juce_OwnedArray.h:89
juce::OwnedArray::~OwnedArray
~OwnedArray()
Definition juce_OwnedArray.h:61
juce::OwnedArray::swap
void swap(int index1, int index2) noexcept
Definition juce_OwnedArray.h:691
juce::OwnedArray::indexOfSorted
int indexOfSorted(ElementComparator &comparator, const ObjectClass *objectToLookFor) const noexcept
Definition juce_OwnedArray.h:840
juce::OwnedArray::insert
ObjectClass * insert(int indexToInsertAt, std::unique_ptr< ObjectClass > newObject)
Definition juce_OwnedArray.h:360
juce::OwnedArray::clearQuick
void clearQuick(bool deleteObjects)
Definition juce_OwnedArray.h:115
juce::OwnedArray::removeObject
void removeObject(const ObjectClass *objectToRemove, bool deleteObject=true)
Definition juce_OwnedArray.h:618
juce::OwnedArray::begin
ObjectClass *const * begin() const noexcept
Definition juce_OwnedArray.h:208
juce::OwnedArray::end
ObjectClass *const * end() const noexcept
Definition juce_OwnedArray.h:224
juce::OwnedArray::end
ObjectClass ** end() noexcept
Definition juce_OwnedArray.h:216
juce::OwnedArray::OwnedArray
OwnedArray()=default
juce::OwnedArray::operator=
OwnedArray & operator=(OwnedArray &&other) noexcept
Definition juce_OwnedArray.h:79
juce::OwnedArray::OwnedArray
OwnedArray(OwnedArray &&other) noexcept
Definition juce_OwnedArray.h:67
juce::OwnedArray::insertArray
void insertArray(int indexToInsertAt, ObjectClass *const *newObjects, int numberOfElements)
Definition juce_OwnedArray.h:377
juce::OwnedArray::move
void move(int currentIndex, int newIndex) noexcept
Definition juce_OwnedArray.h:710
juce::OwnedArray::addSorted
int addSorted(ElementComparator &comparator, ObjectClass *newObject) noexcept
Definition juce_OwnedArray.h:828
juce::OwnedArray::getLock
const TypeOfCriticalSectionToUse & getLock() const noexcept
Definition juce_OwnedArray.h:791
juce::OwnedArray::addArray
void addArray(const std::initializer_list< OtherArrayType > &items)
Definition juce_OwnedArray.h:476
juce::OwnedArray::sort
void sort(ElementComparator &comparator, bool retainOrderOfEquivalentItems=false) noexcept
Definition juce_OwnedArray.h:868
juce::OwnedArray::insert
ObjectClass * insert(int indexToInsertAt, ObjectClass *newObject)
Definition juce_OwnedArray.h:335
juce::OwnedArray::operator[]
ObjectClass * operator[](int index) const noexcept
Definition juce_OwnedArray.h:148
juce::OwnedArray::getRawDataPointer
ObjectClass ** getRawDataPointer() noexcept
Definition juce_OwnedArray.h:191
juce::OwnedArray::data
ObjectClass ** data() noexcept
Definition juce_OwnedArray.h:232
juce::OwnedArray::OwnedArray
OwnedArray(const std::initializer_list< ObjectClass * > &items)
Definition juce_OwnedArray.h:73
juce::OwnedArray::removeRange
void removeRange(int startIndex, int numberToRemove, bool deleteObjects=true)
Definition juce_OwnedArray.h:645
juce::OwnedArray::getLast
ObjectClass * getLast() const noexcept
Definition juce_OwnedArray.h:181
juce::OwnedArray::contains
bool contains(const ObjectClass *objectToLookFor) const noexcept
Definition juce_OwnedArray.h:268