// This code is in the public domain -- Ignacio CastaƱo #pragma once #ifndef NV_CORE_ARRAY_H #define NV_CORE_ARRAY_H /* This array class requires the elements to be relocable; it uses memmove and realloc. Ideally I should be using swap, but I honestly don't care. The only thing that you should be aware of is that internal pointers are not supported. Note also that push_back and resize does not support inserting arguments elements that are in the same container. This is forbidden to prevent an extra copy. */ #include "Memory.h" #include "Debug.h" #include "ForEach.h" // PseudoIndex namespace nv { class Stream; /** * Replacement for std::vector that is easier to debug and provides * some nice foreach enumerators. */ template class NVCORE_CLASS Array { public: typedef uint size_type; // Default constructor. NV_FORCEINLINE Array() : m_buffer(NULL), m_capacity(0), m_size(0) {} // Copy constructor. NV_FORCEINLINE Array(const Array & a) : m_buffer(NULL), m_capacity(0), m_size(0) { copy(a.m_buffer, a.m_size); } // Constructor that initializes the vector with the given elements. NV_FORCEINLINE Array(const T * ptr, uint num) : m_buffer(NULL), m_capacity(0), m_size(0) { copy(ptr, num); } // Allocate array. NV_FORCEINLINE explicit Array(uint capacity) : m_buffer(NULL), m_capacity(0), m_size(0) { setArrayCapacity(capacity); } // Destructor. NV_FORCEINLINE ~Array() { clear(); free(m_buffer); } /// Const element access. NV_FORCEINLINE const T & operator[]( uint index ) const { nvDebugCheck(index < m_size); return m_buffer[index]; } NV_FORCEINLINE const T & at( uint index ) const { nvDebugCheck(index < m_size); return m_buffer[index]; } /// Element access. NV_FORCEINLINE T & operator[] ( uint index ) { nvDebugCheck(index < m_size); return m_buffer[index]; } NV_FORCEINLINE T & at( uint index ) { nvDebugCheck(index < m_size); return m_buffer[index]; } /// Get vector size. NV_FORCEINLINE uint size() const { return m_size; } /// Get vector size. NV_FORCEINLINE uint count() const { return m_size; } /// Get vector capacity. NV_FORCEINLINE uint capacity() const { return m_capacity; } /// Get const vector pointer. NV_FORCEINLINE const T * buffer() const { return m_buffer; } /// Get vector pointer. NV_FORCEINLINE T * buffer() { return m_buffer; } /// Provide begin/end pointers for C++11 range-based for loops. NV_FORCEINLINE T * begin() { return m_buffer; } NV_FORCEINLINE T * end() { return m_buffer + m_size; } NV_FORCEINLINE const T * begin() const { return m_buffer; } NV_FORCEINLINE const T * end() const { return m_buffer + m_size; } /// Is vector empty. NV_FORCEINLINE bool isEmpty() const { return m_size == 0; } /// Is a null vector. NV_FORCEINLINE bool isNull() const { return m_buffer == NULL; } T & append(); void push_back( const T & val ); void pushBack( const T & val ); Array & append( const T & val ); Array & operator<< ( T & t ); void pop_back(); void popBack(uint count = 1); void popFront(uint count = 1); const T & back() const; T & back(); const T & front() const; T & front(); bool contains(const T & e) const; bool find(const T & element, uint * indexPtr) const; bool find(const T & element, uint begin, uint end, uint * indexPtr) const; void removeAt(uint index); bool remove(const T & element); void insertAt(uint index, const T & val = T()); void append(const Array & other); void append(const T other[], uint count); void replaceWithLast(uint index); void resize(uint new_size); void resize(uint new_size, const T & elem); void fill(const T & elem); void clear(); void shrink(); void reserve(uint desired_size); void copy(const T * data, uint count); Array & operator=( const Array & a ); T * release(); // Array enumerator. typedef uint PseudoIndex; NV_FORCEINLINE PseudoIndex start() const { return 0; } NV_FORCEINLINE bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; } NV_FORCEINLINE void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; } #if NV_NEED_PSEUDOINDEX_WRAPPER NV_FORCEINLINE T & operator[]( const PseudoIndexWrapper & i ) { return m_buffer[i(this)]; } NV_FORCEINLINE const T & operator[]( const PseudoIndexWrapper & i ) const { return m_buffer[i(this)]; } #endif // Friends. template friend Stream & operator<< ( Stream & s, Array & p ); template friend void swap(Array & a, Array & b); protected: void setArraySize(uint new_size); void setArrayCapacity(uint new_capacity); T * m_buffer; uint m_capacity; uint m_size; }; } // nv namespace #endif // NV_CORE_ARRAY_H