2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/public-api/common/dali-vector.h>
22 #include <cstring> // for memcpy & memmove
26 VectorBase::VectorBase()
31 VectorBase::~VectorBase()
35 VectorBase::SizeType VectorBase::Capacity() const
37 SizeType capacity = 0u;
40 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
41 capacity = *(metadata - 2u);
46 void VectorBase::Release()
50 // adjust pointer to real beginning
51 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
53 delete[](metadata - 2u);
58 void VectorBase::SetCount(SizeType count)
60 // someone can call Resize( 0u ) before ever populating the vector
63 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
64 *(metadata - 1u) = count;
68 void VectorBase::Reserve(SizeType capacity, SizeType elementSize)
70 SizeType oldCapacity = Capacity();
71 SizeType oldCount = Count();
72 if(capacity > oldCapacity)
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");
78 #if defined(DEBUG_ENABLED)
79 // in debug build this will help identify a vector of uninitialized data
80 memset(wholeData, 0xaa, wholeAllocation);
82 SizeType* metaData = reinterpret_cast<SizeType*>(wholeData);
83 *metaData++ = capacity;
84 *metaData++ = oldCount;
87 // copy over the old data
88 memcpy(metaData, mData, oldCount * elementSize);
96 void VectorBase::Copy(const VectorBase& vector, SizeType elementSize)
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);
110 void VectorBase::Swap(VectorBase& vector)
112 // just swap the data pointers, metadata will swap as side effect
113 std::swap(mData, vector.mData);
116 void VectorBase::Erase(char* address, SizeType elementSize)
118 // erase can be called on an unallocated vector
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);
130 char* VectorBase::Erase(char* first, char* last, SizeType elementSize)
132 char* next = nullptr;
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);
149 void VectorBase::CopyMemory(char* destination, const char* source, size_t numberOfBytes)
151 if(((source < destination) && (source + numberOfBytes > destination)) ||
152 ((destination < source) && (destination + numberOfBytes > source)))
154 // If there is overlap, use memmove.
155 memmove(destination, source, numberOfBytes);
159 // It's safe to use memcpy if there isn't overlap.
160 memcpy(destination, source, numberOfBytes);