| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #ifndef ANKI_UTIL_D_ARRAY_H
- #define ANKI_UTIL_D_ARRAY_H
- #include "anki/util/Allocator.h"
- #include "anki/util/NonCopyable.h"
- #include "anki/util/Functions.h"
- namespace anki {
- /// @addtogroup util_containers
- /// @{
- /// Dynamic array with manual destruction. It doesn't hold the allocator and
- /// that makes it compact. At the same time that requires manual destruction.
- /// Used in permanent classes.
- template<typename T>
- class DArray: public NonCopyable
- {
- public:
- using Value = T;
- using Iterator = Value*;
- using ConstIterator = const Value*;
- using Reference = Value&;
- using ConstReference = const Value&;
- DArray()
- : m_data(nullptr),
- m_size(0)
- {}
- /// Move.
- DArray(DArray&& b)
- : DArray()
- {
- move(b);
- }
- ~DArray()
- {
- ANKI_ASSERT(m_data == nullptr && m_size == 0
- && "Requires manual destruction");
- }
- /// Move.
- DArray& operator=(DArray&& b)
- {
- move(b);
- return *this;
- }
- Reference operator[](const PtrSize n)
- {
- ANKI_ASSERT(n < m_size);
- return m_data[n];
- }
- ConstReference operator[](const PtrSize n) const
- {
- ANKI_ASSERT(n < m_size);
- return m_data[n];
- }
- /// Make it compatible with the C++11 range based for loop.
- Iterator getBegin()
- {
- return &m_data[0];
- }
- /// Make it compatible with the C++11 range based for loop.
- ConstIterator getBegin() const
- {
- return &m_data[0];
- }
- /// Make it compatible with the C++11 range based for loop.
- Iterator getEnd()
- {
- return &m_data[0] + m_size;
- }
- /// Make it compatible with the C++11 range based for loop.
- ConstIterator getEnd() const
- {
- return &m_data[0] + m_size;
- }
- /// Make it compatible with the C++11 range based for loop.
- Iterator begin()
- {
- return getBegin();
- }
- /// Make it compatible with the C++11 range based for loop.
- ConstIterator begin() const
- {
- return getBegin();
- }
- /// Make it compatible with the C++11 range based for loop.
- Iterator end()
- {
- return getEnd();
- }
- /// Make it compatible with the C++11 range based for loop.
- ConstIterator end() const
- {
- return getEnd();
- }
- /// Get first element.
- Reference getFront()
- {
- return m_data[0];
- }
- /// Get first element.
- ConstReference getFront() const
- {
- return m_data[0];
- }
- /// Get last element.
- Reference getBack()
- {
- return m_data[m_size - 1];
- }
- /// Get last element.
- ConstReference getBack() const
- {
- return m_data[m_size - 1];
- }
- /// Get last element.
- ConstReference back() const
- {
- return m_data[m_size - 1];
- }
- PtrSize getSize() const
- {
- return m_size;
- }
- PtrSize getByteSize() const
- {
- return m_size * sizeof(Value);
- }
- Bool isEmpty() const
- {
- return m_size == 0;
- }
- PtrSize getSizeInBytes() const
- {
- return m_size * sizeof(Value);
- }
- /// Create the array.
- template<typename TAllocator>
- ANKI_USE_RESULT Error create(TAllocator alloc, PtrSize size)
- {
- ANKI_ASSERT(m_data == nullptr && m_size == 0);
- Error err = ErrorCode::NONE;
- destroy(alloc);
- if(size > 0)
- {
- m_data = alloc.template newArray<Value>(size);
- if(m_data)
- {
- m_size = size;
- }
- else
- {
- err = ErrorCode::OUT_OF_MEMORY;
- }
- }
- return err;
- }
- /// Create the array.
- template<typename TAllocator>
- ANKI_USE_RESULT Error create(TAllocator alloc, PtrSize size, const Value& v)
- {
- ANKI_ASSERT(m_data == nullptr && m_size == 0);
- Error err = ErrorCode::NONE;
- if(size > 0)
- {
- m_data = alloc.template newArray<Value>(size, v);
- if(m_data)
- {
- m_size = size;
- }
- else
- {
- err = ErrorCode::OUT_OF_MEMORY;
- }
- }
- return err;
- }
- /// Grow the array.
- template<typename TAllocator>
- ANKI_USE_RESULT Error resize(TAllocator alloc, PtrSize size)
- {
- ANKI_ASSERT(size > 0);
- DArray newArr;
- Error err = newArr.create(alloc, size);
- if(!err)
- {
- PtrSize minSize = min<PtrSize>(size, m_size);
- for(U i = 0; i < minSize; i++)
- {
- newArr[i] = std::move((*this)[i]);
- }
- destroy(alloc);
- move(newArr);
- }
- return err;
- }
- /// Destroy the array.
- template<typename TAllocator>
- void destroy(TAllocator alloc)
- {
- if(m_data)
- {
- ANKI_ASSERT(m_size > 0);
- alloc.deleteArray(m_data, m_size);
- m_data = nullptr;
- m_size = 0;
- }
- ANKI_ASSERT(m_data == nullptr && m_size == 0);
- }
- protected:
- Value* m_data;
- U32 m_size;
- void move(DArray& b)
- {
- ANKI_ASSERT(m_data == nullptr && m_size == 0
- && "Cannot move before destroying");
- m_data = b.m_data;
- b.m_data = nullptr;
- m_size = b.m_size;
- b.m_size = 0;
- }
- };
- /// Dynamic array with automatic destruction. It's the same as DArray but it
- /// holds the allocator in order to perform automatic destruction. Use it for
- /// temp operations and on transient classes.
- template<typename T, typename TAlloc = HeapAllocator<T>>
- class DArrayAuto: public DArray<T>
- {
- public:
- using Base = DArray<T>;
- using Value = T;
- using Allocator = TAlloc;
- DArrayAuto(Allocator alloc)
- : Base(),
- m_alloc(alloc)
- {}
- /// Move.
- DArrayAuto(DArrayAuto&& b)
- : DArrayAuto()
- {
- move(b);
- }
- ~DArrayAuto()
- {
- Base::destroy(m_alloc);
- }
- /// Move.
- DArrayAuto& operator=(DArrayAuto&& b)
- {
- move(b);
- return *this;
- }
- /// Create the array.
- ANKI_USE_RESULT Error create(PtrSize size)
- {
- return Base::create(m_alloc, size);
- }
- /// Create the array.
- ANKI_USE_RESULT Error create(PtrSize size, const Value& v)
- {
- return Base::create(m_alloc, size, v);
- }
- /// Grow the array.
- ANKI_USE_RESULT Error resize(PtrSize size)
- {
- return Base::resize(m_alloc, size);
- }
- private:
- Allocator m_alloc;
- void move(DArrayAuto& b)
- {
- Base::move(b);
- m_alloc = b.m_alloc;
- }
- };
- /// Array with preallocated memory.
- template<typename T>
- class SArray: public DArray<T>
- {
- public:
- using Base = DArray<T>;
- using Value = T;
- SArray()
- : Base()
- {}
- SArray(void* mem, PtrSize size)
- : Base()
- {
- ANKI_ASSERT(mem);
- ANKI_ASSERT(size);
- Base::m_data = static_cast<Value*>(mem);
- Base::m_size = size;
- }
- /// Move.
- SArray(SArray&& b)
- : SArray()
- {
- move(b);
- }
- ~SArray()
- {
- #if ANKI_ASSERTIONS
- Base::m_data = nullptr;
- Base::m_size = 0;
- #endif
- }
- /// Move.
- SArray& operator=(SArray&& b)
- {
- move(b);
- return *this;
- }
- private:
- void move(SArray& b)
- {
- Base::m_data = b.m_data;
- b.m_data = nullptr;
- Base::m_size = b.m_size;
- b.m_size = 0;
- }
- };
- /// @}
- } // end namespace anki
- #endif
|