1 #ifndef __DALI_VECTOR_H__
2 #define __DALI_VECTOR_H__
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 // Licensed under the Flora License, Version 1.0 (the License);
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://floralicense.org/license/
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an AS IS BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
25 #include <dali/public-api/common/dali-common.h>
28 * @brief For DALi internal use asserts are enabled in debug builds.
30 * For Application use asserts can be enabled manually.
32 #if defined( DEBUG_ENABLED )
33 #define ENABLE_VECTOR_ASSERTS
36 #if defined( ENABLE_VECTOR_ASSERTS )
37 #define DALI_ASSERT_VECTOR(cond) DALI_ASSERT_ALWAYS(cond)
39 #define DALI_ASSERT_VECTOR(cond)
42 namespace Dali DALI_IMPORT_API
46 * @brief Base class to handle the memory of simple vector.
48 * Memory layout is such that it has two std::size_t to hold the count
49 * and capacity of the vector. mData is adjusted so that it points to the
50 * beginning of the first real item so that iterating the items is quick.
56 typedef std::size_t SizeType;
58 protected: // Construction
61 * @brief Default constructor. Does not allocate space.
68 * Does not release the space. Derived class needs to call Release.
69 * Not virtual as should not be called directly and we do not want
70 * a vtable for this class as it would unnecessarily increase size.
77 * @brief This method is inlined as its needed frequently for End() iterator.
79 * @return The count of elements in this vector.
81 SizeType Count() const
86 SizeType* metadata = reinterpret_cast< SizeType* >( mData );
87 items = *(metadata - 1);
94 * @return The count of elements in this vector.
102 * @return The capacity of this vector.
104 SizeType Capacity() const;
107 * @brief Release the data.
109 * Does not call destructors on objects held.
113 protected: // for Derived classes
116 * @brief Helper to set the count.
118 * @param count Number of elements in the vector.
120 void SetCount( SizeType count );
123 * @brief Reserve space in the vector.
125 * @param count of elements to reserve.
126 * @param elementSize of a single element.
128 void Reserve( SizeType count, SizeType elementSize );
131 * @brief Copy a vector.
133 * @param vector Vector to copy from.
134 * @param elementSize of a single element.
136 void Copy( const VectorBase& vector, SizeType elementSize );
139 * @brief Swap the contents of two vectors.
141 * @param vector Vector to swap with.
143 void Swap( VectorBase& vector );
146 * @brief Erase an element.
148 * Does not change capacity.
149 * @pre last element cannot be erased as there is nothing to move.
150 * @param address to erase from.
151 * @param elementSize to erase.
153 void Erase( char* address, SizeType elementSize );
157 // not copiable as it does not know the size of elements
158 VectorBase( const VectorBase& ); ///< Undefined
159 VectorBase& operator=( const VectorBase& ); ///< Undefined
163 void* mData; ///< Pointer to the data.
168 * @brief Vector algorithm variant for trivial types.
170 * Trivial types do not need destructor or copy constructor called.
172 template< bool IsTrivial >
173 class VectorAlgorithms : public VectorBase
175 protected: // API for deriving classes
177 typedef VectorBase::SizeType SizeType;
180 * @brief Empty constructor.
186 * @brief Empty destructor.
192 * @brief Copy vector contents.
194 * @param rhs to copy from.
195 * @param elementSize of the content.
197 void Copy( const VectorBase& rhs, SizeType elementSize )
199 if( rhs.Capacity() > 0u )
201 VectorBase::Copy( rhs, elementSize );
205 VectorBase::Release();
210 * @brief Reserve space in the vector.
212 * @param count of elements to reserve.
213 * @param elementSize of a single element.
215 void Reserve( SizeType count, SizeType elementSize )
217 VectorBase::Reserve( count, elementSize );
221 * @brief Resize the vector. Does not change capacity.
223 * @param count to resize to.
224 * @param elementSize of a single element.
226 void Resize( SizeType count, SizeType elementSize )
228 // reserve will copy old elements as well
229 Reserve( count, elementSize );
233 * @brief Clear the contents.
235 * For simple types nothing to do.
241 VectorBase::SetCount( 0u );
246 * @brief Release the vector.
250 VectorBase::Release();
254 * @brief Erase an element. Does not change capacity.
256 * @param address to erase from.
257 * @param elementSize to erase.
259 void Erase( char* address, SizeType elementSize )
261 VectorBase::Erase( address, elementSize );
267 * @brief Vector algorithm variant for complex types.
269 * Not yet supported so will lead to compile error
270 * as constructor and destructor are private.
271 * TODO add support for this variant.
274 class VectorAlgorithms< false > : public VectorBase
284 * @brief Vector class with minimum space allocation when its empty.
286 * @param type of the data that the vector holds.
288 template< class T, bool IsTrivialType = __has_trivial_destructor(T) && __has_trivial_copy(T) >
289 class Vector : public VectorAlgorithms< IsTrivialType >
294 * @brief Type definitions.
296 typedef VectorBase::SizeType SizeType;
297 typedef T* Iterator; ///< Most simple Iterator is a pointer
298 typedef const T* ConstIterator;
303 BaseType = IsTrivialType
307 * @brief Default constructor. Does not allocate any space.
313 * @brief Destructor. Releases the allocated space.
321 * @brief Copy constructor.
323 * @param vector Vector to copy from.
325 Vector( const Vector& vector )
332 * @brief Assignment operator.
334 * @param vector Vector to assign from.
335 * @return reference to self for chaining.
337 Vector& operator=( const Vector& vector )
339 if( this != &vector )
341 VectorAlgorithms<BaseType>::Copy( vector, sizeof( ItemType ) );
347 * @return Iterator to the beginning of the data.
349 Iterator Begin() const
351 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
356 * @return Iterator to the end of the data (one past last element).
360 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
361 address += VectorBase::Count();
366 * @param index of the element.
367 * @return reference to the element for given index.
369 ItemType& operator[]( SizeType index )
371 // reuse the const version
372 return const_cast< ItemType& >( const_cast< const Vector< ItemType >& >( *this )[ index ] );
376 * @param index of the element.
377 * @return reference to the element for given index.
379 const ItemType& operator[]( SizeType index ) const
381 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
382 DALI_ASSERT_VECTOR( index < VectorBase::Count() && "Index out of bounds" );
383 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
389 * @brief Push back an element to the vector.
391 * @param element to be added.
393 void PushBack( const ItemType& element )
395 const SizeType count = VectorBase::Count();
396 const SizeType newCount = count + 1u;
397 const SizeType capacity = VectorBase::Capacity();
398 if( newCount > capacity )
401 Reserve( newCount << 1 ); // reserve double the current count
403 // set new count first as otherwise the debug assert will hit us
404 VectorBase::SetCount( newCount );
405 operator[]( count ) = element;
409 * @brief Reserve space in the vector.
411 * Reserving less than current Capacity is a no-op.
412 * @param count of elements to reserve.
414 void Reserve( SizeType count )
416 VectorAlgorithms<BaseType>::Reserve( count, sizeof( ItemType ) );
420 * @brief Resize the vector. Does not change capacity.
422 * @param count to resize to.
423 * @param item to insert to the new indeces.
425 void Resize( SizeType count, ItemType item = ItemType() )
427 const SizeType oldCount = VectorBase::Count();
428 if( count <= oldCount )
430 // getting smaller so just set count
431 VectorBase::SetCount( count );
435 // remember how many new items get added
436 SizeType newItems = count - oldCount;
438 for( ; newItems > 0; --newItems )
446 * @brief Erase an element.
448 * Does not change capacity. Other elements get moved.
449 * @param iterator Iterator pointing to item to remove.
450 * @return Iterator pointing to next element.
452 Iterator Erase( Iterator iterator )
454 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
455 DALI_ASSERT_VECTOR( (iterator < End()) && (iterator >= Begin() ) && "Iterator not inside vector" );
456 if( iterator < ( End() - 1 ) )
458 VectorAlgorithms<BaseType>::Erase( reinterpret_cast< char* >( iterator ), sizeof( ItemType ) );
462 // just remove the element
469 * @brief Removes an element.
471 * Does not maintain order. Swaps the element with end and
472 * decreases size by one. This is much faster than Erase so use
473 * this in case order does not matter. Does not change capacity.
475 * @param iterator Iterator pointing to item to remove.
477 void Remove( Iterator iterator )
479 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
480 Iterator end = End();
481 DALI_ASSERT_VECTOR( (iterator < end) && (iterator >= Begin() ) && "Iterator not inside vector" );
482 Iterator last = end - 1;
483 if( last != iterator )
485 std::swap( *iterator, *last );
487 VectorBase::SetCount( VectorBase::Count() - 1 );
491 * @brief Swap the contents of two vectors.
493 * @param vector Vector to swap with.
495 void Swap( Vector& vector )
497 VectorBase::Swap( vector );
501 * @brief Clear the contents of the vector. Keeps its capacity.
505 VectorAlgorithms<BaseType>::Clear();
509 * @brief Release the memory that the vector holds.
513 VectorAlgorithms<BaseType>::Release();
520 #endif /* __DALI_VECTOR_H__ */