c8ec3a69b1c30326caf983d1c8054aa3610d9753
[iec.git] / src / type3_AndroidCloud / anbox-master / external / android-emugl / shared / emugl / common / pod_vector.cpp
1 // Copyright (C) 2014 The Android Open Source Project
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 #include "emugl/common/pod_vector.h"
16
17 #include <stdlib.h>
18 #include <string.h>
19
20 #define USE_MALLOC_USABLE_SIZE 0
21
22 namespace emugl {
23
24 static inline void swapPointers(char** p1, char** p2) {
25     char* tmp = *p1;
26     *p1 = *p2;
27     *p2 = tmp;
28 }
29
30 PodVectorBase::PodVectorBase(const PodVectorBase& other) {
31     initFrom(other.begin(), other.byteSize());
32 }
33
34 PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) {
35     initFrom(other.begin(), other.byteSize());
36     return *this;
37 }
38
39 PodVectorBase::~PodVectorBase() {
40     if (mBegin) {
41         // Sanity.
42         ::memset(mBegin, 0xee, byteSize());
43         ::free(mBegin);
44         mBegin = NULL;
45         mEnd = NULL;
46         mLimit = NULL;
47     }
48 }
49
50 void PodVectorBase::initFrom(const void* from, size_t fromLen) {
51     if (!fromLen || !from) {
52         mBegin = NULL;
53         mEnd = NULL;
54         mLimit = NULL;
55     } else {
56         mBegin = static_cast<char*>(::malloc(fromLen));
57         mEnd = mLimit = mBegin + fromLen;
58         ::memcpy(mBegin, from, fromLen);
59     }
60 }
61
62 void PodVectorBase::assignFrom(const PodVectorBase& other) {
63     resize(other.byteSize(), 1U);
64     ::memmove(begin(), other.begin(), byteSize());
65 }
66
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;
71
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);
76         }
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;
83             } else {
84                 newCapacity = newCapacity2;
85             }
86         }
87         reserve(newCapacity, itemSize);
88     }
89     mEnd = mBegin + newSize * itemSize;
90 }
91
92 void PodVectorBase::reserve(size_t newSize, size_t itemSize) {
93     if (newSize == 0) {
94         ::free(mBegin);
95         mBegin = NULL;
96         mEnd = NULL;
97         mLimit = NULL;
98         return;
99     }
100
101     size_t oldByteSize = byteSize();
102     size_t newByteCapacity = newSize * itemSize;
103     char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity));
104     mBegin = newBegin;
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);
110     }
111 #endif
112     mLimit = newBegin + newByteCapacity;
113     // Sanity.
114     if (newByteCapacity > oldByteSize) {
115         ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize);
116     }
117 }
118
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);
127     }
128 }
129
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,
136                   mBegin + pos,
137                   count * itemSize - pos);
138         // Sanity to avoid copying pointers and other bad stuff.
139         ::memset(mBegin + pos, 0, itemSize);
140     }
141     return mBegin + pos;
142 }
143
144 void PodVectorBase::swapAll(PodVectorBase* other) {
145     swapPointers(&mBegin, &other->mBegin);
146     swapPointers(&mEnd, &other->mEnd);
147     swapPointers(&mLimit, &other->mLimit);
148 }
149
150 }  // namespace emugl