Clean up the code to build successfully on macOS
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-vector.cpp
1 /*
2  * Copyright (c) 2020 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 <cstring> // for memcpy & memmove
23
24 namespace Dali
25 {
26 VectorBase::VectorBase()
27 : mData(nullptr)
28 {
29 }
30
31 VectorBase::~VectorBase()
32 {
33 }
34
35 VectorBase::SizeType VectorBase::Capacity() const
36 {
37   SizeType capacity = 0u;
38   if(mData)
39   {
40     SizeType* metadata = reinterpret_cast<SizeType*>(mData);
41     capacity           = *(metadata - 2u);
42   }
43   return capacity;
44 }
45
46 void VectorBase::Release()
47 {
48   if(mData)
49   {
50     // adjust pointer to real beginning
51     SizeType* metadata = reinterpret_cast<SizeType*>(mData);
52
53     delete[](metadata - 2u);
54     mData = nullptr;
55   }
56 }
57
58 void VectorBase::SetCount(SizeType count)
59 {
60   // someone can call Resize( 0u ) before ever populating the vector
61   if(mData)
62   {
63     SizeType* metadata = reinterpret_cast<SizeType*>(mData);
64     *(metadata - 1u)   = count;
65   }
66 }
67
68 void VectorBase::Reserve(SizeType capacity, SizeType elementSize)
69 {
70   SizeType oldCapacity = Capacity();
71   SizeType oldCount    = Count();
72   if(capacity > oldCapacity)
73   {
74     const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
75     void*          wholeData       = reinterpret_cast<void*>(new uint8_t[wholeAllocation]);
76     DALI_ASSERT_ALWAYS(wholeData && "VectorBase::Reserve - Memory allocation failed");
77
78 #if defined(DEBUG_ENABLED)
79     // in debug build this will help identify a vector of uninitialized data
80     memset(wholeData, 0xaa, wholeAllocation);
81 #endif
82     SizeType* metaData = reinterpret_cast<SizeType*>(wholeData);
83     *metaData++        = capacity;
84     *metaData++        = oldCount;
85     if(mData)
86     {
87       // copy over the old data
88       memcpy(metaData, mData, oldCount * elementSize);
89       // release old buffer
90       Release();
91     }
92     mData = metaData;
93   }
94 }
95
96 void VectorBase::Copy(const VectorBase& vector, SizeType elementSize)
97 {
98   // release old data
99   Release();
100   // reserve space based on source capacity
101   const SizeType capacity = vector.Capacity();
102   Reserve(capacity, elementSize);
103   // copy over whole data
104   const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
105   SizeType*      srcData         = reinterpret_cast<SizeType*>(vector.mData);
106   SizeType*      dstData         = reinterpret_cast<SizeType*>(mData);
107   memcpy(dstData - 2u, srcData - 2u, wholeAllocation);
108 }
109
110 void VectorBase::Swap(VectorBase& vector)
111 {
112   // just swap the data pointers, metadata will swap as side effect
113   std::swap(mData, vector.mData);
114 }
115
116 void VectorBase::Erase(char* address, SizeType elementSize)
117 {
118   // erase can be called on an unallocated vector
119   if(mData)
120   {
121     uint8_t*       startAddress  = reinterpret_cast<uint8_t*>(address) + elementSize;
122     const uint8_t* endAddress    = reinterpret_cast<uint8_t*>(mData) + Count() * elementSize;
123     SizeType       numberOfBytes = endAddress - startAddress;
124     // addresses overlap so use memmove
125     memmove(address, startAddress, numberOfBytes);
126     SetCount(Count() - 1u);
127   }
128 }
129
130 char* VectorBase::Erase(char* first, char* last, SizeType elementSize)
131 {
132   char* next = nullptr;
133
134   if(mData)
135   {
136     uint8_t*       startAddress  = reinterpret_cast<uint8_t*>(last);
137     const uint8_t* endAddress    = reinterpret_cast<uint8_t*>(mData) + Count() * elementSize;
138     SizeType       numberOfBytes = endAddress - startAddress;
139     // addresses overlap so use memmove
140     memmove(first, startAddress, numberOfBytes);
141     SetCount(Count() - (last - first) / elementSize);
142
143     next = first;
144   }
145
146   return next;
147 }
148
149 void VectorBase::CopyMemory(char* destination, const char* source, size_t numberOfBytes)
150 {
151   if(((source < destination) && (source + numberOfBytes > destination)) ||
152      ((destination < source) && (destination + numberOfBytes > source)))
153   {
154     // If there is overlap, use memmove.
155     memmove(destination, source, numberOfBytes);
156   }
157   else
158   {
159     // It's safe to use memcpy if there isn't overlap.
160     memcpy(destination, source, numberOfBytes);
161   }
162 }
163
164 } // namespace Dali