diff options
Diffstat (limited to 'emulator/opengl/shared/emugl/common/pod_vector.cpp')
| -rw-r--r-- | emulator/opengl/shared/emugl/common/pod_vector.cpp | 151 | 
1 files changed, 151 insertions, 0 deletions
| diff --git a/emulator/opengl/shared/emugl/common/pod_vector.cpp b/emulator/opengl/shared/emugl/common/pod_vector.cpp new file mode 100644 index 0000000..3fe8f15 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/pod_vector.cpp @@ -0,0 +1,151 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/pod_vector.h" + +#include <stdlib.h> +#include <string.h> + +#define USE_MALLOC_USABLE_SIZE 0 + +namespace emugl { + +static inline void swapPointers(char** p1, char** p2) { +    char* tmp = *p1; +    *p1 = *p2; +    *p2 = tmp; +} + +PodVectorBase::PodVectorBase(const PodVectorBase& other) { +    initFrom(other.begin(), other.byteSize()); +} + +PodVectorBase& PodVectorBase::operator=(const PodVectorBase& other) { +    initFrom(other.begin(), other.byteSize()); +    return *this; +} + +PodVectorBase::~PodVectorBase() { +    if (mBegin) { +        // Sanity. +        ::memset(mBegin, 0xee, byteSize()); +        ::free(mBegin); +        mBegin = NULL; +        mEnd = NULL; +        mLimit = NULL; +    } +} + +void PodVectorBase::initFrom(const void* from, size_t fromLen) { +    if (!fromLen || !from) { +        mBegin = NULL; +        mEnd = NULL; +        mLimit = NULL; +    } else { +        mBegin = static_cast<char*>(::malloc(fromLen)); +        mEnd = mLimit = mBegin + fromLen; +        ::memcpy(mBegin, from, fromLen); +    } +} + +void PodVectorBase::assignFrom(const PodVectorBase& other) { +    resize(other.byteSize(), 1U); +    ::memmove(begin(), other.begin(), byteSize()); +} + +void PodVectorBase::resize(size_t newSize, size_t itemSize) { +    const size_t kMaxSize = maxItemCapacity(itemSize); +    size_t oldCapacity = itemCapacity(itemSize); +    const size_t kMinCapacity = 256 / itemSize; + +    if (newSize < oldCapacity) { +        // Only shrink if the new size is really small. +        if (newSize < oldCapacity / 2 && oldCapacity > kMinCapacity) { +            reserve(newSize, itemSize); +        } +    } else if (newSize > oldCapacity) { +        size_t newCapacity = oldCapacity; +        while (newCapacity < newSize) { +            size_t newCapacity2 = newCapacity + (newCapacity >> 2) + 8; +            if (newCapacity2 < newCapacity || newCapacity > kMaxSize) { +                newCapacity = kMaxSize; +            } else { +                newCapacity = newCapacity2; +            } +        } +        reserve(newCapacity, itemSize); +    } +    mEnd = mBegin + newSize * itemSize; +} + +void PodVectorBase::reserve(size_t newSize, size_t itemSize) { +    const size_t kMaxSize = maxItemCapacity(itemSize); +    if (newSize == 0) { +        ::free(mBegin); +        mBegin = NULL; +        mEnd = NULL; +        mLimit = NULL; +        return; +    } + +    size_t oldByteSize = byteSize(); +    size_t newByteCapacity = newSize * itemSize; +    char* newBegin = static_cast<char*>(::realloc(mBegin, newByteCapacity)); +    mBegin = newBegin; +    mEnd = newBegin + oldByteSize; +#if USE_MALLOC_USABLE_SIZE +    size_t usableSize = malloc_usable_size(mBegin); +    if (usableSize > newByteCapacity) { +        newByteCapacity = usableSize - (usableSize % itemSize); +    } +#endif +    mLimit = newBegin + newByteCapacity; +    // Sanity. +    if (newByteCapacity > oldByteSize) { +        ::memset(mBegin + oldByteSize, 0, newByteCapacity - oldByteSize); +    } +} + +void PodVectorBase::removeAt(size_t itemPos, size_t itemSize) { +    size_t count = itemCount(itemSize); +    if (itemPos < count) { +        size_t  pos = itemPos * itemSize; +        ::memmove(mBegin + pos, +                  mBegin + pos + itemSize, +                  byteSize() - pos - itemSize); +        resize(count - 1U, itemSize); +    } +} + +void* PodVectorBase::insertAt(size_t itemPos, size_t itemSize) { +    size_t count = this->itemCount(itemSize); +    resize(count + 1, itemSize); +    size_t pos = itemPos * itemSize; +    if (itemPos < count) { +        ::memmove(mBegin + pos + itemSize, +                  mBegin + pos, +                  count * itemSize - pos); +        // Sanity to avoid copying pointers and other bad stuff. +        ::memset(mBegin + pos, 0, itemSize); +    } +    return mBegin + pos; +} + +void PodVectorBase::swapAll(PodVectorBase* other) { +    swapPointers(&mBegin, &other->mBegin); +    swapPointers(&mEnd, &other->mEnd); +    swapPointers(&mLimit, &other->mLimit); +} + +}  // namespace emugl | 
