[SRUK] Initial copy from Tizen 2.2 version
[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 Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/public-api/common/dali-vector.h>
19
20 // EXTERNAL INCLUDES
21 #include <stdlib.h>
22 #include <memory.h>
23
24 namespace Dali
25 {
26
27 VectorBase::VectorBase()
28   : mData( NULL )
29 {
30 }
31
32 VectorBase::~VectorBase()
33 {
34 }
35
36 VectorBase::SizeType VectorBase::Capacity() const
37 {
38   SizeType capacity = 0;
39   if( mData )
40   {
41     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
42     capacity = *(metadata - 2);
43   }
44   return capacity;
45 }
46
47
48 void VectorBase::Release()
49 {
50   if( mData )
51   {
52     // adjust pointer to real beginning
53     SizeType* metadata = reinterpret_cast< SizeType* >( mData );
54     // TODO would be nice to memset to a bitpattern to catch illegal use of container after release
55     // but that would require knowledge of the itemsize
56     free( metadata - 2 );
57     mData = 0;
58   }
59 }
60
61 void VectorBase::SetCount( SizeType count )
62 {
63   // Setcount is internal so should not be called on empty vector
64   DALI_ASSERT_DEBUG( mData && "Vector is empty" );
65   SizeType* metadata = reinterpret_cast< SizeType* >( mData );
66   *(metadata - 1) = count;
67 }
68
69 void VectorBase::Reserve( SizeType capacity, SizeType elementSize )
70 {
71   SizeType oldCapacity = Capacity();
72   SizeType oldCount = Count();
73   if( capacity > oldCapacity )
74   {
75     const SizeType wholeAllocation = sizeof(SizeType) * 2 + capacity * elementSize;
76     void* wholeData = (void*)malloc( wholeAllocation );
77 #if defined( DEBUG_ENABLED )
78     // in debug build this will help identify a vector of uninitialized data
79     memset( wholeData, 0xaa, wholeAllocation );
80 #endif
81     SizeType* metaData = reinterpret_cast< SizeType* >( wholeData );
82     *metaData++ = capacity;
83     *metaData++ = oldCount;
84     if( mData )
85     {
86       // copy over the old data
87       memcpy( metaData, mData, oldCount * elementSize );
88       // release old buffer
89       Release();
90     }
91     mData = metaData;
92   }
93 }
94
95 void VectorBase::Copy( const VectorBase& vector, SizeType elementSize )
96 {
97   if( this != &vector )
98   {
99     // release old data
100     Release();
101     // reserve space based on source capacity
102     const SizeType capacity = vector.Capacity();
103     Reserve( capacity, elementSize );
104     // copy over whole data
105     const SizeType wholeAllocation = sizeof(SizeType) * 2 + capacity * elementSize;
106     SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData );
107     SizeType* dstData = reinterpret_cast< SizeType* >( mData );
108     memcpy( dstData - 2, srcData - 2, wholeAllocation );
109   }
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   char* startAddress = address + elementSize;
121   const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
122   SizeType numberOfBytes = endAddress - startAddress;
123   // addresses overlap so use memmove
124   memmove( address, startAddress, numberOfBytes );
125   SetCount( Count() - 1 );
126 }
127
128 } // namespace Dali
129