diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/shared/general/HACD/public/PxVector.h | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'APEX_1.4/shared/general/HACD/public/PxVector.h')
| -rw-r--r-- | APEX_1.4/shared/general/HACD/public/PxVector.h | 594 |
1 files changed, 594 insertions, 0 deletions
diff --git a/APEX_1.4/shared/general/HACD/public/PxVector.h b/APEX_1.4/shared/general/HACD/public/PxVector.h new file mode 100644 index 00000000..4364761a --- /dev/null +++ b/APEX_1.4/shared/general/HACD/public/PxVector.h @@ -0,0 +1,594 @@ + + +#ifndef PX_FOUNDATION_VECTOR_H +#define PX_FOUNDATION_VECTOR_H + +#include "PlatformConfigHACD.h" + +/*! +** +** Copyright (c) 2015 by John W. Ratcliff mailto:[email protected] +** +** +** The MIT license: +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is furnished +** to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. + +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +** +** If you find this code snippet useful; you can tip me at this bitcoin address: +** +** BITCOIN TIP JAR: "1BT66EoaGySkbY9J6MugvQRhMMXDwPxPya" +** + +*/ + +namespace hacd +{ + + /*! + An array is a sequential container. + + Implementation note + * entries between 0 and size are valid objects + * we use inheritance to build this because the array is included inline in a lot + of objects and we want the allocator to take no space if it's not stateful, which + aggregation doesn't allow. Also, we want the metadata at the front for the inline + case where the allocator contains some inline storage space + */ + template<class T> + class vector + { + + public: + + typedef T* iterator; + typedef const T* const_iterator; + + + explicit vector(const PxEmpty& v) + { + HACD_UNUSED(v); + if(mData) + mCapacity |= HACD_SIGN_BITMASK; + } + + /*! + Default array constructor. Initialize an empty array + */ + HACD_INLINE explicit vector(void) + : mData(0), mSize(0), mCapacity(0) + {} + + /*! + Initialize array with given capacity + */ + HACD_INLINE explicit vector(uint32_t size, const T& a = T()) + : mData(0), mSize(0), mCapacity(0) + { + resize(size, a); + } + + // This is necessary else the basic default copy constructor is used in the case of both arrays being of the same template instance + // The C++ standard clearly states that a template constructor is never a copy constructor [2]. In other words, + // the presence of a template constructor does not suppress the implicit declaration of the copy constructor. + // Also never make a copy constructor explicit, or copy-initialization* will no longer work. This is because + // 'binding an rvalue to a const reference requires an accessible copy constructor' (http://gcc.gnu.org/bugs/) + // *http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-assignment-initializ + HACD_INLINE vector(const vector& other) + { + copy(other); + } + + /*! + Initialize array with given length + */ + HACD_INLINE explicit vector(const T* first, const T* last) + : mSize(last<first?0:(uint32_t)(last-first)), mCapacity(mSize) + { + mData = allocate(mSize); + copy(mData, mData + mSize, first); + } + + /*! + Destructor + */ + HACD_INLINE ~vector() + { + destroy(mData, mData + mSize); + + if(capacity() && !isInUserMemory()) + deallocate(mData); + } + + /*! + Assignment operator. Copy content (deep-copy) + */ + HACD_INLINE vector& operator= (const vector<T>& rhs) + { + if(&rhs == this) + return *this; + + clear(); + reserve(rhs.mSize); + copy(mData, mData + rhs.mSize, rhs.mData); + + mSize = rhs.mSize; + return *this; + } + + /*! + vector indexing operator. + \param i + The index of the element that will be returned. + \return + The element i in the array. + */ + HACD_FORCE_INLINE const T& operator[] (uint32_t i) const + { + HACD_ASSERT(i < mSize); + return mData[i]; + } + + /*! + vector indexing operator. + \param i + The index of the element that will be returned. + \return + The element i in the array. + */ + HACD_FORCE_INLINE T& operator[] (uint32_t i) + { + HACD_ASSERT(i < mSize); + return mData[i]; + } + + /*! + Returns a pointer to the initial element of the array. + \return + a pointer to the initial element of the array. + */ + HACD_FORCE_INLINE const_iterator begin() const + { + return mData; + } + + HACD_FORCE_INLINE iterator begin() + { + return mData; + } + + /*! + Returns an iterator beyond the last element of the array. Do not dereference. + \return + a pointer to the element beyond the last element of the array. + */ + + HACD_FORCE_INLINE const_iterator end() const + { + return mData+mSize; + } + + HACD_FORCE_INLINE iterator end() + { + return mData+mSize; + } + + /*! + Returns a reference to the first element of the array. Undefined if the array is empty. + \return a reference to the first element of the array + */ + + HACD_FORCE_INLINE const T& front() const + { + HACD_ASSERT(mSize); + return mData[0]; + } + + HACD_FORCE_INLINE T& front() + { + HACD_ASSERT(mSize); + return mData[0]; + } + + /*! + Returns a reference to the last element of the array. Undefined if the array is empty + \return a reference to the last element of the array + */ + + HACD_FORCE_INLINE const T& back() const + { + HACD_ASSERT(mSize); + return mData[mSize-1]; + } + + HACD_FORCE_INLINE T& back() + { + HACD_ASSERT(mSize); + return mData[mSize-1]; + } + + + /*! + Returns the number of entries in the array. This can, and probably will, + differ from the array capacity. + \return + The number of of entries in the array. + */ + HACD_FORCE_INLINE uint32_t size() const + { + return mSize; + } + + /*! + Clears the array. + */ + HACD_INLINE void clear() + { + destroy(mData, mData + mSize); + mSize = 0; + } + + /*! + Returns whether the array is empty (i.e. whether its size is 0). + \return + true if the array is empty + */ + HACD_FORCE_INLINE bool empty() const + { + return mSize==0; + } + + /*! + Finds the first occurrence of an element in the array. + \param a + The element to find. + */ + + + HACD_INLINE iterator find(const T& a) + { + uint32_t index; + for(index=0;index<mSize && mData[index]!=a;index++) + ; + return mData+index; + } + + HACD_INLINE const_iterator find(const T& a) const + { + uint32_t index; + for(index=0;index<mSize && mData[index]!=a;index++) + ; + return mData+index; + } + + + ///////////////////////////////////////////////////////////////////////// + /*! + Adds one element to the end of the array. Operation is O(1). + \param a + The element that will be added to this array. + */ + ///////////////////////////////////////////////////////////////////////// + + HACD_FORCE_INLINE T& push_back(const T& a) + { + if(capacity()<=mSize) + grow(capacityIncrement()); + + HACD_PLACEMENT_NEW((void*)(mData + mSize),T)(a); + + return mData[mSize++]; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Returns the element at the end of the array. Only legal if the array is non-empty. + */ + ///////////////////////////////////////////////////////////////////////// + HACD_INLINE T pop_back() + { + HACD_ASSERT(mSize); + T t = mData[mSize-1]; + mData[--mSize].~T(); + return t; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Construct one element at the end of the array. Operation is O(1). + */ + ///////////////////////////////////////////////////////////////////////// + HACD_INLINE T& insert() + { + if(capacity()<=mSize) + grow(capacityIncrement()); + + return *(new (mData+mSize++)T); + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Subtracts the element on position i from the array and replace it with + the last element. + Operation is O(1) + \param i + The position of the element that will be subtracted from this array. + \return + The element that was removed. + */ + ///////////////////////////////////////////////////////////////////////// + HACD_INLINE void replaceWithLast(uint32_t i) + { + HACD_ASSERT(i<mSize); + mData[i] = mData[--mSize]; + mData[mSize].~T(); + } + + HACD_INLINE void replaceWithLast(iterator i) + { + replaceWithLast(static_cast<uint32_t>(i-mData)); + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Replaces the first occurrence of the element a with the last element + Operation is O(n) + \param i + The position of the element that will be subtracted from this array. + \return Returns true if the element has been removed. + */ + ///////////////////////////////////////////////////////////////////////// + + HACD_INLINE bool findAndReplaceWithLast(const T& a) + { + uint32_t index = 0; + while(index<mSize && mData[index]!=a) + ++index; + if(index == mSize) + return false; + replaceWithLast(index); + return true; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Subtracts the element on position i from the array. Shift the entire + array one step. + Operation is O(n) + \param i + The position of the element that will be subtracted from this array. + */ + ///////////////////////////////////////////////////////////////////////// + HACD_INLINE void remove(uint32_t i) + { + HACD_ASSERT(i<mSize); + for(T* it=mData+i; it->~T(), ++i<mSize; ++it) + new(it)T(mData[i]); + + --mSize; + } + + ///////////////////////////////////////////////////////////////////////// + /*! + Removes a range from the array. Shifts the array so order is maintained. + Operation is O(n) + \param begin + The starting position of the element that will be subtracted from this array. + \param end + The ending position of the elment that will be subtracted from this array. + */ + ///////////////////////////////////////////////////////////////////////// + HACD_INLINE void removeRange(uint32_t begin,uint32_t count) + { + HACD_ASSERT(begin<mSize); + HACD_ASSERT( (begin+count) <= mSize ); + for (uint32_t i=0; i<count; i++) + { + mData[begin+i].~T(); // call the destructor on the ones being removed first. + } + T *dest = &mData[begin]; // location we are copying the tail end objects to + T *src = &mData[begin+count]; // start of tail objects + uint32_t move_count = mSize - (begin+count); // compute remainder that needs to be copied down + for (uint32_t i=0; i<move_count; i++) + { + new ( dest ) T(*src); // copy the old one to the new location + src->~T(); // call the destructor on the old location + dest++; + src++; + } + mSize-=count; + } + + + ////////////////////////////////////////////////////////////////////////// + /*! + Resize array + */ + ////////////////////////////////////////////////////////////////////////// + HACD_NOINLINE void resize(const uint32_t size, const T& a = T()); + + ////////////////////////////////////////////////////////////////////////// + /*! + Resize array such that only as much memory is allocated to hold the + existing elements + */ + ////////////////////////////////////////////////////////////////////////// + HACD_INLINE void shrink() + { + recreate(mSize); + } + + + ////////////////////////////////////////////////////////////////////////// + /*! + Deletes all array elements and frees memory. + */ + ////////////////////////////////////////////////////////////////////////// + HACD_INLINE void reset() + { + resize(0); + shrink(); + } + + + ////////////////////////////////////////////////////////////////////////// + /*! + Ensure that the array has at least size capacity. + */ + ////////////////////////////////////////////////////////////////////////// + HACD_INLINE void reserve(const uint32_t capacity) + { + if(capacity > this->capacity()) + grow(capacity); + } + + ////////////////////////////////////////////////////////////////////////// + /*! + Query the capacity(allocated mem) for the array. + */ + ////////////////////////////////////////////////////////////////////////// + HACD_FORCE_INLINE uint32_t capacity() const + { + return mCapacity & ~HACD_SIGN_BITMASK; + } + + protected: + + HACD_NOINLINE void copy(const vector<T>& other) + { + if(!other.empty()) + { + mData = allocate(mSize = mCapacity = other.size()); + copy(mData, mData + mSize, other.begin()); + } + else + { + mData = NULL; + mSize = 0; + mCapacity = 0; + } + + //mData = allocate(other.mSize); + //mSize = other.mSize; + //mCapacity = other.mSize; + //copy(mData, mData + mSize, other.mData); + + } + + HACD_INLINE T* allocate(uint32_t size) + { + return size ? (T*)HACD_ALLOC(sizeof(T) * size) : 0; + } + + HACD_INLINE void deallocate(void* mem) + { + HACD_FREE(mem); + } + + static HACD_INLINE void create(T* first, T* last, const T& a) + { + for(; first<last; ++first) + ::new(first)T(a); + } + + static HACD_INLINE void copy(T* first, T* last, const T* src) + { + for(; first<last; ++first, ++src) + ::new (first)T(*src); + } + + static HACD_INLINE void destroy(T* first, T* last) + { + for(; first<last; ++first) + first->~T(); + } + + /*! + Resizes the available memory for the array. + + \param capacity + The number of entries that the set should be able to hold. + */ + HACD_INLINE void grow(uint32_t capacity) + { + HACD_ASSERT(this->capacity() < capacity); + recreate(capacity); + } + + /*! + Creates a new memory block, copies all entries to the new block and destroys old entries. + + \param capacity + The number of entries that the set should be able to hold. + */ + HACD_NOINLINE void recreate(uint32_t capacity); + + // The idea here is to prevent accidental brain-damage with push_back or insert. Unfortunately + // it interacts badly with InlineArrays with smaller inline allocations. + // TODO(dsequeira): policy template arg, this is exactly what they're for. + HACD_INLINE uint32_t capacityIncrement() const + { + const uint32_t capacity = this->capacity(); + return capacity == 0 ? 1 : capacity * 2; + } + + // We need one bit to mark arrays that have been deserialized from a user-provided memory block. + // For alignment & memory saving purpose we store that bit in the rarely used capacity member. + HACD_FORCE_INLINE uint32_t isInUserMemory() const + { + return mCapacity & HACD_SIGN_BITMASK; + } + + public: // need to be public for serialization + + T* mData; + uint32_t mSize; + + protected: + + uint32_t mCapacity; + }; + + template<class T> + HACD_NOINLINE void vector<T>::resize(const uint32_t size, const T& a) + { + reserve(size); + create(mData + mSize, mData + size, a); + destroy(mData + size, mData + mSize); + mSize = size; + } + + template<class T> + HACD_NOINLINE void vector<T>::recreate(uint32_t capacity) + { + T* newData = allocate(capacity); + HACD_ASSERT(!capacity || newData && newData != mData); + + copy(newData, newData + mSize, mData); + destroy(mData, mData + mSize); + if(!isInUserMemory()) + deallocate(mData); + + mData = newData; + mCapacity = capacity; + } + +} // namespace hacd + +#endif |