- SparseArrayView class

We need this to merge the game specific sector/wall extensions with the base but still allow the engine to access such arrays. For that they need a runtime settable stride.
This commit is contained in:
Christoph Oelckers 2021-11-07 12:02:45 +01:00
parent 477a2a23e6
commit 94f40d11ae
2 changed files with 185 additions and 0 deletions

View file

@ -25,6 +25,17 @@
</Expand>
</Type>
<Type Name="TSparseArrayView&lt;*&gt;">
<DisplayString>Size = {Count}</DisplayString>
<Expand>
<Item Name="Size">Count</Item>
<ArrayItems>
<Size>Count</Size>
<ValuePointer>(value_type*)Array</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="TStaticPointedArray&lt;*&gt;">
<DisplayString>Size = {Count}</DisplayString>
<Expand>

View file

@ -106,6 +106,7 @@ protected:
};
// TArray -------------------------------------------------------------------
// Must match TArray's layout.
@ -1807,3 +1808,176 @@ private:
T *Array;
unsigned int Count;
};
template<typename T> class TSparseIterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
TSparseIterator(unsigned char* ptr = nullptr, unsigned stride = 0) { m_Ptr = ptr; Stride = stride; }
// Comparison operators
bool operator==(const TSparseIterator &other) const { return m_Ptr == other.m_Ptr; }
bool operator!=(const TSparseIterator &other) const { return m_Ptr != other.m_Ptr; }
bool operator< (const TSparseIterator &other) const { return m_Ptr < other.m_Ptr; }
bool operator<=(const TSparseIterator &other) const { return m_Ptr <= other.m_Ptr; }
bool operator> (const TSparseIterator &other) const { return m_Ptr > other.m_Ptr; }
bool operator>=(const TSparseIterator &other) const { return m_Ptr >= other.m_Ptr; }
// Arithmetic operators
TSparseIterator &operator++() { m_Ptr += Stride; return *this; }
TSparseIterator operator++(int) { auto tmp = *this; ++*this; return tmp; }
TSparseIterator &operator--() { m_Ptr -= Stride; return *this; }
TSparseIterator operator--(int) { auto tmp = *this; --*this; return tmp; }
TSparseIterator &operator+=(difference_type offset) { m_Ptr += offset * Stride; return *this; }
TSparseIterator operator+(difference_type offset) const { return TSparseIterator(m_Ptr + offset * Stride, Stride); }
friend TSparseIterator operator+(difference_type offset, const TSparseIterator &other) { return TSparseIterator(offset*other.Stride + other.m_Ptr, other.Stride); }
TSparseIterator &operator-=(difference_type offset) { m_Ptr -= offset * Stride; return *this; }
TSparseIterator operator-(difference_type offset) const { return TSparseIterator(m_Ptr - offset * Stride, Stride); }
difference_type operator-(const TSparseIterator &other) const { return (m_Ptr - other.m_Ptr) / Stride; }
// Random access operators
T& operator[](difference_type i) { return *(T*)(m_Ptr + i * Stride); }
const T& operator[](difference_type i) const { return *(T*)(m_Ptr + i * Stride); }
T &operator*() const { return (T*)m_Ptr; }
T* operator->() { return (T*)m_Ptr; }
protected:
unsigned char* m_Ptr;
unsigned Stride;
};
// A wrapper to externally stored data.
// Like the above but with a customizable stride
template <class T>
class TSparseArrayView
{
public:
typedef TSparseIterator<T> iterator;
typedef TSparseIterator<const T> const_iterator;
typedef T value_type;
iterator begin()
{
return iterator(Array, Stride);
}
const_iterator begin() const
{
return const_iterator(Array, Stride);
}
const_iterator cbegin() const
{
return const_iterator(Array, Stride);
}
iterator end()
{
return iterator(Array + Count * Stride, Stride);
}
const_iterator end() const
{
return const_iterator(Array + Count * Stride, Stride);
}
const_iterator cend() const
{
return const_iterator(Array + Count * Stride, Stride);
}
////////
TSparseArrayView() = default; // intended to keep this type trivial.
TSparseArrayView(T *data, unsigned stride, unsigned count = 0)
{
Count = count;
Array = data;
Stride = stride;
}
TSparseArrayView(const TSparseArrayView<T> &other) = default;
TSparseArrayView<T> &operator= (const TSparseArrayView<T> &other) = default;
// Check equality of two arrays
bool operator==(const TArrayView<T> &other) const
{
if (Count != other.Count)
{
return false;
}
for (unsigned int i = 0; i < Count; ++i)
{
if (Element(i) != other.Element(i))
{
return false;
}
}
return true;
}
T &Element(size_t index)
{
return (T*)Array[index*Stride];
}
// Return a reference to an element
T &operator[] (size_t index) const
{
return Element(index);
}
// Returns a reference to the last element
T &Last() const
{
return Element(Count - 1);
}
// returns address of first element
T *Data() const
{
return &Element(0);
}
unsigned Size() const
{
return Count;
}
unsigned int Find(const T& item) const
{
unsigned int i;
for (i = 0; i < Count; ++i)
{
if (Element(i) == item)
break;
}
return i;
}
void Set(T *data, unsigned stride, unsigned count)
{
Array = reinterpret_cast<unsigned char*>(data);
Count = count;
Stride = stride;
}
void Set(void *data, unsigned stride, unsigned count)
{
Array = reinterpret_cast<unsigned char*>(data);
Count = count;
Stride = stride;
}
void Clear()
{
Count = 0;
Stride = 0;
Array = nullptr;
}
private:
unsigned char* Array;
unsigned int Count;
unsigned int Stride;
};