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.
21 * @addtogroup CAPI_DALI_FRAMEWORK
29 #include <dali/public-api/common/dali-common.h>
32 * For DALi internal use asserts are enabled in debug builds.
33 * For Application use asserts can be enabled manually.
35 #if defined( DEBUG_ENABLED )
36 #define ENABLE_VECTOR_ASSERTS
39 #if defined( ENABLE_VECTOR_ASSERTS )
40 #define DALI_ASSERT_VECTOR(cond) DALI_ASSERT_ALWAYS(cond)
42 #define DALI_ASSERT_VECTOR(cond)
45 namespace Dali DALI_IMPORT_API
49 * Base class to handle the memory of simple vector.
50 * Memory layout is such that it has two std::size_t to hold the count
51 * and capacity of the vector. mData is adjusted so that it points to the
52 * beginning of the first real item so that iterating the items is quick.
58 typedef std::size_t SizeType;
60 protected: // Construction
63 * Default constructor. Does not allocate space.
68 * Destructor. 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 * This method is inlined as its needed frequently for End() iterator.
78 * @return The count of elements in this vector.
80 SizeType Count() const
85 SizeType* metadata = reinterpret_cast< SizeType* >( mData );
86 items = *(metadata - 1);
93 * @return The count of elements in this vector.
101 * @return The capacity of this vector.
103 SizeType Capacity() const;
107 * Does not call destructors on objects held.
111 protected: // for Derived classes
114 * Helper to set the count.
115 * @param count Number of elements in the vector.
117 void SetCount( SizeType count );
120 * Reserve space in the vector.
121 * @param count of elements to reserve.
122 * @param elementSize of a single element.
124 void Reserve( SizeType count, SizeType elementSize );
128 * @param vector Vector to copy from.
129 * @param elementSize of a single element.
131 void Copy( const VectorBase& vector, SizeType elementSize );
134 * Swap the contents of two vectors.
135 * @param vector Vector to swap with.
137 void Swap( VectorBase& vector );
140 * Erase an element. Does not change capacity.
141 * @pre last element cannot be erased as there is nothing to move.
142 * @param address to erase from.
143 * @param elementSize to erase.
145 void Erase( char* address, SizeType elementSize );
149 // not copiable as it does not know the size of elements
150 VectorBase( const VectorBase& );
151 VectorBase& operator=( const VectorBase& );
160 * Vector algorithm variant for trivial types.
161 * Trivial types do not need destructor or copy constructor called.
163 template< bool IsTrivial >
164 class VectorAlgorithms : public VectorBase
166 protected: // API for deriving classes
168 typedef VectorBase::SizeType SizeType;
183 * Copy vector contents.
184 * @param rhs to copy from.
185 * @param elementSize of the content.
187 void Copy( const VectorBase& rhs, SizeType elementSize )
189 if( rhs.Capacity() > 0u )
191 VectorBase::Copy( rhs, elementSize );
195 VectorBase::Release();
200 * Reserve space in the vector.
201 * @param count of elements to reserve.
202 * @param elementSize of a single element.
204 void Reserve( SizeType count, SizeType elementSize )
206 VectorBase::Reserve( count, elementSize );
210 * Resize the vector. Does not change capacity.
211 * @param count to resize to.
212 * @param elementSize of a single element.
214 void Resize( SizeType count, SizeType elementSize )
216 // reserve will copy old elements as well
217 Reserve( count, elementSize );
221 * Clear the contents. For simple types nothing to do.
227 VectorBase::SetCount( 0u );
232 * Release the vector.
236 VectorBase::Release();
240 * Erase an element. Does not change capacity.
241 * @param address to erase from.
242 * @param elementSize to erase.
244 void Erase( char* address, SizeType elementSize )
246 VectorBase::Erase( address, elementSize );
252 * Vector algorithm variant for complex types.
253 * Not yet supported so will lead to compile error
254 * as constructor and destructor are private.
255 * TODO add support for this variant.
258 class VectorAlgorithms< false > : public VectorBase
268 * Vector class with minimum space allocation when its empty.
269 * @param type of the data that the vector holds.
271 template< class T, bool IsTrivialType = __has_trivial_destructor(T) && __has_trivial_copy(T) >
272 class Vector : public VectorAlgorithms< IsTrivialType >
279 typedef VectorBase::SizeType SizeType;
280 typedef T* Iterator; /// Most simple Iterator is a pointer
281 typedef const T* ConstIterator;
285 BaseType = IsTrivialType
289 * Default constructor. Does not allocate any space.
295 * Destructor. Releases the allocated space.
304 * @param vector Vector to copy from.
306 Vector( const Vector& vector )
313 * Assignment operator
314 * @param vector Vector to assign from.
315 * @return reference to self for chaining.
317 Vector& operator=( const Vector& vector )
319 if( this != &vector )
321 VectorAlgorithms<BaseType>::Copy( vector, sizeof( ItemType ) );
327 * @return Iterator to the beginning of the data.
329 Iterator Begin() const
331 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
336 * @return Iterator to the end of the data (one past last element).
340 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
341 address += VectorBase::Count();
346 * @param index of the element.
347 * @return reference to the element for given index.
349 ItemType& operator[]( SizeType index )
351 // reuse the const version
352 return const_cast< ItemType& >( const_cast< const Vector< ItemType >& >( *this )[ index ] );
356 * @param index of the element.
357 * @return reference to the element for given index.
359 const ItemType& operator[]( SizeType index ) const
361 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
362 DALI_ASSERT_VECTOR( index < VectorBase::Count() && "Index out of bounds" );
363 ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
369 * Push back an element to the vector.
370 * @param element to be added.
372 void PushBack( const ItemType& element )
374 const SizeType count = VectorBase::Count();
375 const SizeType newCount = count + 1u;
376 const SizeType capacity = VectorBase::Capacity();
377 if( newCount > capacity )
380 Reserve( newCount << 1 ); // reserve double the current count
382 // set new count first as otherwise the debug assert will hit us
383 VectorBase::SetCount( newCount );
384 operator[]( count ) = element;
388 * Reserve space in the vector.
389 * Reserving less than current Capacity is a no-op.
390 * @param count of elements to reserve.
392 void Reserve( SizeType count )
394 VectorAlgorithms<BaseType>::Reserve( count, sizeof( ItemType ) );
398 * Resize the vector. Does not change capacity.
399 * @param count to resize to.
400 * @param item to insert to the new indeces.
402 void Resize( SizeType count, ItemType item = ItemType() )
404 const SizeType oldCount = VectorBase::Count();
405 if( count <= oldCount )
407 // getting smaller so just set count
408 VectorBase::SetCount( count );
412 // remember how many new items get added
413 SizeType newItems = count - oldCount;
415 for( ; newItems > 0; --newItems )
423 * Erase an element. Does not change capacity.
424 * Other elements get moved.
425 * @param iterator Iterator pointing to item to remove.
426 * @return Iterator pointing to next element.
428 Iterator Erase( Iterator iterator )
430 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
431 DALI_ASSERT_VECTOR( (iterator < End()) && (iterator >= Begin() ) && "Iterator not inside vector" );
432 if( iterator < ( End() - 1 ) )
434 VectorAlgorithms<BaseType>::Erase( reinterpret_cast< char* >( iterator ), sizeof( ItemType ) );
438 // just remove the element
445 * Removes an element. Does not maintain order.
446 * Swaps the element with end and decreases size by one.
447 * This is much faster than Erase so use this in case order
448 * does not matter. Does not change capacity.
449 * @param iterator Iterator pointing to item to remove.
451 void Remove( Iterator iterator )
453 DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
454 Iterator end = End();
455 DALI_ASSERT_VECTOR( (iterator < end) && (iterator >= Begin() ) && "Iterator not inside vector" );
456 Iterator last = end - 1;
457 if( last != iterator )
459 std::swap( *iterator, *last );
461 VectorBase::SetCount( VectorBase::Count() - 1 );
465 * Swap the contents of two vectors.
466 * @param vector Vector to swap with.
468 void Swap( Vector& vector )
470 VectorBase::Swap( vector );
474 * Clear the contents of the vector. Keeps its capacity.
478 VectorAlgorithms<BaseType>::Clear();
482 * Release the memory that the vector holds.
486 VectorAlgorithms<BaseType>::Release();
496 #endif /* __DALI_VECTOR_H__ */