1 // Copyright (C) 2014 The Android Open Source Project
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "emugl/common/pod_vector.h"
20 #define USE_MALLOC_USABLE_SIZE 0
24 static inline void swapPointers(char** p1, char** p2) {
30 PodVectorBase::PodVectorBase(const PodVectorBase& other) {
31 initFrom(other.begin(), other.byteSize());
34 PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) {
35 initFrom(other.begin(), other.byteSize());
39 PodVectorBase::~PodVectorBase() {
42 ::memset(mBegin, 0xee, byteSize());
50 void PodVectorBase::initFrom(const void* from, size_t fromLen) {
51 if (!fromLen || !from) {
56 mBegin = static_cast<char*>(::malloc(fromLen));
57 mEnd = mLimit = mBegin + fromLen;
58 ::memcpy(mBegin, from, fromLen);
62 void PodVectorBase::assignFrom(const PodVectorBase& other) {
63 resize(other.byteSize(), 1U);
64 ::memmove(begin(), other.begin(), byteSize());
67 void PodVectorBase::resize(size_t newSize, size_t itemSize) {
68 const size_t kMaxSize = maxItemCapacity(itemSize);
69 size_t oldCapacity = itemCapacity(itemSize);
70 const size_t kMinCapacity = 256 / itemSize;
72 if (newSize < oldCapacity) {
73 // Only shrink if the new size is really small.
74 if (newSize < oldCapacity / 2 && oldCapacity > kMinCapacity) {
75 reserve(newSize, itemSize);
77 } else if (newSize > oldCapacity) {
78 size_t newCapacity = oldCapacity;
79 while (newCapacity < newSize) {
80 size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8;
81 if (newCapacity2 < newCapacity || newCapacity > kMaxSize) {
82 newCapacity = kMaxSize;
84 newCapacity = newCapacity2;
87 reserve(newCapacity, itemSize);
89 mEnd = mBegin + newSize * itemSize;
92 void PodVectorBase::reserve(size_t newSize, size_t itemSize) {
101 size_t oldByteSize = byteSize();
102 size_t newByteCapacity = newSize * itemSize;
103 char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity));
105 mEnd = newBegin + oldByteSize;
106 #if USE_MALLOC_USABLE_SIZE
107 size_t usableSize = malloc_usable_size(mBegin);
108 if (usableSize > newByteCapacity) {
109 newByteCapacity = usableSize - (usableSize % itemSize);
112 mLimit = newBegin + newByteCapacity;
114 if (newByteCapacity > oldByteSize) {
115 ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize);
119 void PodVectorBase::removeAt(size_t itemPos, size_t itemSize) {
120 size_t count = itemCount(itemSize);
121 if (itemPos < count) {
122 size_t pos = itemPos * itemSize;
123 ::memmove(mBegin + pos,
124 mBegin + pos + itemSize,
125 byteSize() - pos - itemSize);
126 resize(count - 1U, itemSize);
130 void* PodVectorBase::insertAt(size_t itemPos, size_t itemSize) {
131 size_t count = this->itemCount(itemSize);
132 resize(count + 1, itemSize);
133 size_t pos = itemPos * itemSize;
134 if (itemPos < count) {
135 ::memmove(mBegin + pos + itemSize,
137 count * itemSize - pos);
138 // Sanity to avoid copying pointers and other bad stuff.
139 ::memset(mBegin + pos, 0, itemSize);
144 void PodVectorBase::swapAll(PodVectorBase* other) {
145 swapPointers(&mBegin, &other->mBegin);
146 swapPointers(&mEnd, &other->mEnd);
147 swapPointers(&mLimit, &other->mLimit);