Merge "Extend Animation duration when an animator exceeds current duration." into...
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-vector.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/public-api/common/dali-vector.h>
20
21 // EXTERNAL INCLUDES
22 #include <stdlib.h>
23 #include <memory.h>
24
25 namespace Dali
26 {
27
28 VectorBase::VectorBase()
29   : mData( NULL )
30 {
31 }
32
33 VectorBase::~VectorBase()
34 {
35 }
36
37 VectorBase::SizeType VectorBase::Capacity() const
38 {
39   SizeType capacity = 0u;
40   if( mData )
41   {
42     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
43     capacity = *(metadata - 2u);
44   }
45   return capacity;
46 }
47
48
49 void VectorBase::Release()
50 {
51   if( mData )
52   {
53     // adjust pointer to real beginning
54     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
55     // TODO would be nice to memset to a bitpattern to catch illegal use of container after release
56     // but that would require knowledge of the itemsize
57     free( metadata - 2u );
58     mData = 0u;
59   }
60 }
61
62 void VectorBase::SetCount( SizeType count )
63 {
64   // someone can call Resize( 0u ) before ever populating the vector
65   if( mData )
66   {
67     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
68     *(metadata - 1u) = count;
69   }
70 }
71
72 void VectorBase::Reserve( SizeType capacity, SizeType elementSize )
73 {
74   SizeType oldCapacity = Capacity();
75   SizeType oldCount = Count();
76   if( capacity > oldCapacity )
77   {
78     const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
79     void* wholeData = (void*)malloc( wholeAllocation );
80 #if defined( DEBUG_ENABLED )
81     // in debug build this will help identify a vector of uninitialized data
82     memset( wholeData, 0xaa, wholeAllocation );
83 #endif
84     SizeType* metaData = reinterpret_cast< SizeType* >( wholeData );
85     *metaData++ = capacity;
86     *metaData++ = oldCount;
87     if( mData )
88     {
89       // copy over the old data
90       memcpy( metaData, mData, oldCount * elementSize );
91       // release old buffer
92       Release();
93     }
94     mData = metaData;
95   }
96 }
97
98 void VectorBase::Copy( const VectorBase& vector, SizeType elementSize )
99 {
100   // release old data
101   Release();
102   // reserve space based on source capacity
103   const SizeType capacity = vector.Capacity();
104   Reserve( capacity, elementSize );
105   // copy over whole data
106   const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
107   SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData );
108   SizeType* dstData = reinterpret_cast< SizeType* >( mData );
109   memcpy( dstData - 2u, srcData - 2u, wholeAllocation );
110 }
111
112 void VectorBase::Swap( VectorBase& vector )
113 {
114   // just swap the data pointers, metadata will swap as side effect
115   std::swap( mData, vector.mData );
116 }
117
118 void VectorBase::Erase( char* address, SizeType elementSize )
119 {
120   // erase can be called on an unallocated vector
121   if( mData )
122   {
123     char* startAddress = address + elementSize;
124     const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
125     SizeType numberOfBytes = endAddress - startAddress;
126     // addresses overlap so use memmove
127     memmove( address, startAddress, numberOfBytes );
128     SetCount( Count() - 1u );
129   }
130 }
131
132 char* VectorBase::Erase( char* first, char* last, SizeType elementSize )
133 {
134   char* next = NULL;
135
136   if( mData )
137   {
138     char* startAddress = last;
139     const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
140     SizeType numberOfBytes = endAddress - startAddress;
141     // addresses overlap so use memmove
142     memmove( first, startAddress, numberOfBytes );
143     SetCount( Count() - ( last - first ) / elementSize );
144
145     next = first;
146   }
147
148   return next;
149 }
150
151 void VectorBase::CopyMemory( char* destination, const char* source, size_t numberOfBytes )
152 {
153   if( ( ( source < destination ) && ( source + numberOfBytes > destination ) ) ||
154       ( ( destination < source ) && ( destination + numberOfBytes > source ) ) )
155   {
156     // If there is overlap, use memmove.
157     memmove( destination, source, numberOfBytes );
158   }
159   else
160   {
161     // It's safe to use memcpy if there isn't overlap.
162     memcpy( destination, source, numberOfBytes );
163   }
164 }
165
166 } // namespace Dali
167