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() = default;
33 VectorBase::SizeType VectorBase::Capacity() const
35 SizeType capacity = 0u;
38 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
39 capacity = *(metadata - 2u);
44 void VectorBase::Release()
48 // adjust pointer to real beginning
49 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
51 delete[](metadata - 2u);
56 void VectorBase::SetCount(SizeType count)
58 // someone can call Resize( 0u ) before ever populating the vector
61 SizeType* metadata = reinterpret_cast<SizeType*>(mData);
62 *(metadata - 1u) = count;
66 void VectorBase::Reserve(SizeType capacity, SizeType elementSize)
68 SizeType oldCapacity = Capacity();
69 SizeType oldCount = Count();
70 if(capacity > oldCapacity)
72 const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
73 void* wholeData = reinterpret_cast<void*>(new uint8_t[wholeAllocation]);
74 DALI_ASSERT_ALWAYS(wholeData && "VectorBase::Reserve - Memory allocation failed");
76 #if defined(DEBUG_ENABLED)
77 // in debug build this will help identify a vector of uninitialized data
78 memset(wholeData, 0xaa, wholeAllocation);
80 SizeType* metaData = reinterpret_cast<SizeType*>(wholeData);
81 *metaData++ = capacity;
82 *metaData++ = oldCount;
85 // copy over the old data
86 memcpy(metaData, mData, oldCount * elementSize);
94 void VectorBase::Copy(const VectorBase& vector, SizeType elementSize)
98 // reserve space based on source capacity
99 const SizeType capacity = vector.Capacity();
100 Reserve(capacity, elementSize);
101 // copy over whole data
102 const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
103 SizeType* srcData = reinterpret_cast<SizeType*>(vector.mData);
104 SizeType* dstData = reinterpret_cast<SizeType*>(mData);
105 memcpy(dstData - 2u, srcData - 2u, wholeAllocation);
108 void VectorBase::Swap(VectorBase& vector)
110 // just swap the data pointers, metadata will swap as side effect
111 std::swap(mData, vector.mData);
114 void VectorBase::Erase(char* address, SizeType elementSize)
116 // erase can be called on an unallocated vector
119 uint8_t* startAddress = reinterpret_cast<uint8_t*>(address) + elementSize;
120 const uint8_t* endAddress = reinterpret_cast<uint8_t*>(mData) + Count() * elementSize;
121 SizeType numberOfBytes = endAddress - startAddress;
122 // addresses overlap so use memmove
123 memmove(address, startAddress, numberOfBytes);
124 SetCount(Count() - 1u);
128 char* VectorBase::Erase(char* first, char* last, SizeType elementSize)
130 char* next = nullptr;
134 uint8_t* startAddress = reinterpret_cast<uint8_t*>(last);
135 const uint8_t* endAddress = reinterpret_cast<uint8_t*>(mData) + Count() * elementSize;
136 SizeType numberOfBytes = endAddress - startAddress;
137 // addresses overlap so use memmove
138 memmove(first, startAddress, numberOfBytes);
139 SetCount(Count() - (last - first) / elementSize);
147 void VectorBase::CopyMemory(char* destination, const char* source, size_t numberOfBytes)
149 if(((source < destination) && (source + numberOfBytes > destination)) ||
150 ((destination < source) && (destination + numberOfBytes > source)))
152 // If there is overlap, use memmove.
153 memmove(destination, source, numberOfBytes);
157 // It's safe to use memcpy if there isn't overlap.
158 memcpy(destination, source, numberOfBytes);