| @@ -11,7 +11,8 @@ | |||||
| // | // | ||||
| // The Array class | // The Array class | ||||
| // --------------- | // --------------- | ||||
| // A very simple Array class not unlike the std::vector. | |||||
| // A very simple Array class not unlike the std::vector, with some nice | |||||
| // additional features, eg. Array<int,float> for automatic arrays of structs. | |||||
| // | // | ||||
| #if !defined __LOL_ARRAY_H__ | #if !defined __LOL_ARRAY_H__ | ||||
| @@ -22,22 +23,27 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| template<typename T1, typename T2 = void, typename T3 = void> class Array | |||||
| /* | |||||
| * The base array type | |||||
| * FIXME: only works properly with POD types for now | |||||
| */ | |||||
| template<typename T> class ArrayBase | |||||
| { | { | ||||
| public: | public: | ||||
| typedef struct { T1 m1; T2 m2; T3 m3; } Element; | |||||
| typedef T Element; | |||||
| inline Array() : m_data(0), m_count(0), m_reserved(0) {} | |||||
| inline ~Array() { delete[] m_data; } | |||||
| inline ArrayBase() : m_data(0), m_count(0), m_reserved(0) {} | |||||
| inline ~ArrayBase() { delete[] m_data; } | |||||
| Array(Array const& that) : m_data(0), m_count(0), m_reserved(0) | |||||
| ArrayBase(ArrayBase const& that) : m_data(0), m_count(0), m_reserved(0) | |||||
| { | { | ||||
| Reserve(that.m_reserved); | Reserve(that.m_reserved); | ||||
| memcpy(m_data, that.m_data, m_count * sizeof(Element)); | memcpy(m_data, that.m_data, m_count * sizeof(Element)); | ||||
| m_count = that.m_count; | m_count = that.m_count; | ||||
| } | } | ||||
| Array& operator=(Array const& that) | |||||
| ArrayBase& operator=(ArrayBase const& that) | |||||
| { | { | ||||
| m_data = 0; | m_data = 0; | ||||
| m_count = 0; | m_count = 0; | ||||
| @@ -58,38 +64,24 @@ public: | |||||
| return m_data[n]; | return m_data[n]; | ||||
| } | } | ||||
| inline Array<T1, T2, T3> const& operator<<(Element const &x) | |||||
| inline ArrayBase<T> const& operator<<(T const &x) | |||||
| { | { | ||||
| if (m_count >= m_reserved) | if (m_count >= m_reserved) | ||||
| { | { | ||||
| /* Protect ourselves against insertion of an element that is | |||||
| * already in m_data. */ | |||||
| Element tmp = x; | |||||
| T tmp = x; | |||||
| Reserve(m_count * 13 / 8 + 8); | Reserve(m_count * 13 / 8 + 8); | ||||
| m_data[m_count++] = tmp; | m_data[m_count++] = tmp; | ||||
| } | } | ||||
| else | else | ||||
| { | |||||
| m_data[m_count++] = x; | m_data[m_count++] = x; | ||||
| } | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3) | |||||
| inline void Append(T const &x) | |||||
| { | { | ||||
| if (m_count >= m_reserved) | |||||
| { | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; | |||||
| Reserve(m_count * 13 / 8 + 8); | |||||
| m_data[m_count].m1 = tmp1; | |||||
| m_data[m_count].m2 = tmp2; | |||||
| m_data[m_count].m3 = tmp3; | |||||
| } | |||||
| else | |||||
| { | |||||
| m_data[m_count].m1 = m1; | |||||
| m_data[m_count].m2 = m2; | |||||
| m_data[m_count].m3 = m3; | |||||
| } | |||||
| ++m_count; | |||||
| *this << x; | |||||
| } | } | ||||
| void Remove(int pos) | void Remove(int pos) | ||||
| @@ -122,203 +114,289 @@ public: | |||||
| inline int Count() const { return m_count; } | inline int Count() const { return m_count; } | ||||
| inline int Bytes() const { return m_count * sizeof(Element); } | inline int Bytes() const { return m_count * sizeof(Element); } | ||||
| private: | |||||
| protected: | |||||
| Element *m_data; | Element *m_data; | ||||
| int m_count, m_reserved; | int m_count, m_reserved; | ||||
| }; | }; | ||||
| template<typename T1, typename T2> class Array<T1, T2, void> | |||||
| /* | |||||
| * Element types | |||||
| */ | |||||
| template<typename T1, typename T2, typename T3 = void, typename T4 = void, | |||||
| typename T5 = void, typename T6 = void, typename T7 = void, | |||||
| typename T8 = void> | |||||
| class ArrayElement | |||||
| { | { | ||||
| public: | public: | ||||
| typedef struct { T1 m1; T2 m2; } Element; | |||||
| T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6; T7 m7; T8 m8; | |||||
| }; | |||||
| inline Array() : m_data(0), m_count(0), m_reserved(0) {} | |||||
| inline ~Array() { delete[] m_data; } | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5, | |||||
| typename T6, typename T7> | |||||
| class ArrayElement<T1, T2, T3, T4, T5, T6, T7, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6; T7 m7; | |||||
| }; | |||||
| Array(Array const& that) : m_data(0), m_count(0), m_reserved(0) | |||||
| { | |||||
| Reserve(that.m_reserved); | |||||
| memcpy(m_data, that.m_data, m_count * sizeof(Element)); | |||||
| m_count = that.m_count; | |||||
| } | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5, | |||||
| typename T6> | |||||
| class ArrayElement<T1, T2, T3, T4, T5, T6, void, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; T6 m6; | |||||
| }; | |||||
| Array& operator=(Array const& that) | |||||
| { | |||||
| m_data = 0; | |||||
| m_count = 0; | |||||
| m_reserved = 0; | |||||
| Reserve(that.m_reserved); | |||||
| memcpy(m_data, that.m_data, that.m_count * sizeof(Element)); | |||||
| m_count = that.m_count; | |||||
| return *this; | |||||
| } | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5> | |||||
| class ArrayElement<T1, T2, T3, T4, T5, void, void, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; T3 m3; T4 m4; T5 m5; | |||||
| }; | |||||
| inline Element& operator[](int n) | |||||
| { | |||||
| return m_data[n]; | |||||
| } | |||||
| template<typename T1, typename T2, typename T3, typename T4> | |||||
| class ArrayElement<T1, T2, T3, T4, void, void, void, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; T3 m3; T4 m4; | |||||
| }; | |||||
| inline Element const& operator[](int n) const | |||||
| { | |||||
| return m_data[n]; | |||||
| } | |||||
| template<typename T1, typename T2, typename T3> | |||||
| class ArrayElement<T1, T2, T3, void, void, void, void, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; T3 m3; | |||||
| }; | |||||
| template<typename T1, typename T2> | |||||
| class ArrayElement<T1, T2, void, void, void, void, void, void> | |||||
| { | |||||
| public: | |||||
| T1 m1; T2 m2; | |||||
| }; | |||||
| /* | |||||
| * Array specialisations implementing specific setters | |||||
| */ | |||||
| inline Array<T1, T2> const& operator<<(Element const &x) | |||||
| template<typename T1, typename T2 = void, typename T3 = void, | |||||
| typename T4 = void, typename T5 = void, typename T6 = void, | |||||
| typename T7 = void, typename T8 = void> | |||||
| class Array : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, T7, T8> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4, | |||||
| T5 const &m5, T6 const &m6, T7 const &m7, T8 const &m8) | |||||
| { | { | ||||
| if (m_count >= m_reserved) | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | { | ||||
| /* Protect ourselves against insertion of an element that is | |||||
| * already in m_data. */ | |||||
| Element tmp = x; | |||||
| Reserve(m_count * 13 / 8 + 8); | |||||
| m_data[m_count++] = tmp; | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4; | |||||
| T5 tmp5 = m5; T6 tmp6 = m6; T7 tmp7 = m7; T8 tmp8 = m8; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| this->m_data[this->m_count].m4 = tmp4; | |||||
| this->m_data[this->m_count].m5 = tmp5; | |||||
| this->m_data[this->m_count].m6 = tmp6; | |||||
| this->m_data[this->m_count].m7 = tmp7; | |||||
| this->m_data[this->m_count].m8 = tmp8; | |||||
| } | } | ||||
| else | else | ||||
| m_data[m_count++] = x; | |||||
| return *this; | |||||
| { | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| this->m_data[this->m_count].m4 = m4; | |||||
| this->m_data[this->m_count].m5 = m5; | |||||
| this->m_data[this->m_count].m6 = m6; | |||||
| this->m_data[this->m_count].m7 = m7; | |||||
| this->m_data[this->m_count].m8 = m8; | |||||
| } | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| inline void Append(T1 const &m1, T2 const &m2) | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5, | |||||
| typename T6, typename T7> | |||||
| class Array<T1, T2, T3, T4, T5, T6, T7, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, T7, void> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4, | |||||
| T5 const &m5, T6 const &m6, T7 const &m7) | |||||
| { | { | ||||
| if (m_count >= m_reserved) | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | { | ||||
| T1 tmp1 = m1; T2 tmp2 = m2; | |||||
| Reserve(m_count * 13 / 8 + 8); | |||||
| m_data[m_count].m1 = tmp1; | |||||
| m_data[m_count].m2 = tmp2; | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4; | |||||
| T5 tmp5 = m5; T6 tmp6 = m6; T7 tmp7 = m7; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| this->m_data[this->m_count].m4 = tmp4; | |||||
| this->m_data[this->m_count].m5 = tmp5; | |||||
| this->m_data[this->m_count].m6 = tmp6; | |||||
| this->m_data[this->m_count].m7 = tmp7; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| m_data[m_count].m1 = m1; | |||||
| m_data[m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| this->m_data[this->m_count].m4 = m4; | |||||
| this->m_data[this->m_count].m5 = m5; | |||||
| this->m_data[this->m_count].m6 = m6; | |||||
| this->m_data[this->m_count].m7 = m7; | |||||
| } | } | ||||
| ++m_count; | |||||
| } | |||||
| void Remove(int pos) | |||||
| { | |||||
| memmove(m_data + pos, m_data + pos + 1, m_count - pos - 1); | |||||
| m_count--; | |||||
| } | |||||
| void Remove(int pos, int count) | |||||
| { | |||||
| memmove(m_data + pos, m_data + pos + count, m_count - pos - count); | |||||
| m_count -= count; | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| void Reserve(int count) | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5, | |||||
| typename T6> | |||||
| class Array<T1, T2, T3, T4, T5, T6, void, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, T6, void, void> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4, | |||||
| T5 const &m5, T6 const &m6) | |||||
| { | { | ||||
| if (count <= (int)m_reserved) | |||||
| return; | |||||
| Element *tmp = new Element[count]; | |||||
| if (m_data) | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | { | ||||
| memcpy(tmp, m_data, m_count * sizeof(Element)); | |||||
| delete[] m_data; | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4; | |||||
| T5 tmp5 = m5; T6 tmp6 = m6; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| this->m_data[this->m_count].m4 = tmp4; | |||||
| this->m_data[this->m_count].m5 = tmp5; | |||||
| this->m_data[this->m_count].m6 = tmp6; | |||||
| } | } | ||||
| m_data = tmp; | |||||
| m_reserved = count; | |||||
| else | |||||
| { | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| this->m_data[this->m_count].m4 = m4; | |||||
| this->m_data[this->m_count].m5 = m5; | |||||
| this->m_data[this->m_count].m6 = m6; | |||||
| } | |||||
| ++this->m_count; | |||||
| } | } | ||||
| inline int Count() const { return m_count; } | |||||
| inline int Bytes() const { return m_count * sizeof(Element); } | |||||
| private: | |||||
| Element *m_data; | |||||
| int m_count, m_reserved; | |||||
| }; | }; | ||||
| template<typename T1> class Array<T1, void, void> | |||||
| template<typename T1, typename T2, typename T3, typename T4, typename T5> | |||||
| class Array<T1, T2, T3, T4, T5, void, void, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, T3, T4, T5, void, void, void> > | |||||
| { | { | ||||
| public: | public: | ||||
| typedef T1 Element; | |||||
| inline Array() : m_data(0), m_count(0), m_reserved(0) {} | |||||
| inline ~Array() { delete[] m_data; } | |||||
| Array(Array const& that) : m_data(0), m_count(0), m_reserved(0) | |||||
| { | |||||
| Reserve(that.m_reserved); | |||||
| memcpy(m_data, that.m_data, m_count * sizeof(Element)); | |||||
| m_count = that.m_count; | |||||
| } | |||||
| Array& operator=(Array const& that) | |||||
| { | |||||
| m_data = 0; | |||||
| m_count = 0; | |||||
| m_reserved = 0; | |||||
| Reserve(that.m_reserved); | |||||
| memcpy(m_data, that.m_data, that.m_count * sizeof(Element)); | |||||
| m_count = that.m_count; | |||||
| return *this; | |||||
| } | |||||
| inline Element& operator[](int n) | |||||
| { | |||||
| return m_data[n]; | |||||
| } | |||||
| inline Element const& operator[](int n) const | |||||
| { | |||||
| return m_data[n]; | |||||
| } | |||||
| inline Array<T1> const& operator<<(T1 const &x) | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4, | |||||
| T5 const &m5) | |||||
| { | { | ||||
| if (m_count >= m_reserved) | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | { | ||||
| T1 tmp = x; | |||||
| Reserve(m_count * 13 / 8 + 8); | |||||
| m_data[m_count++] = tmp; | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4; | |||||
| T5 tmp5 = m5; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| this->m_data[this->m_count].m4 = tmp4; | |||||
| this->m_data[this->m_count].m5 = tmp5; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| m_data[m_count++] = x; | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| this->m_data[this->m_count].m4 = m4; | |||||
| this->m_data[this->m_count].m5 = m5; | |||||
| } | } | ||||
| return *this; | |||||
| } | |||||
| inline void Append(T1 const &x) | |||||
| { | |||||
| *this << x; | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| void Remove(int pos) | |||||
| template<typename T1, typename T2, typename T3, typename T4> | |||||
| class Array<T1, T2, T3, T4, void, void, void, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, T3, T4, void, void, void, void> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3, T4 const &m4) | |||||
| { | { | ||||
| memmove(m_data + pos, m_data + pos + 1, m_count - pos - 1); | |||||
| m_count--; | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; T4 tmp4 = m4; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| this->m_data[this->m_count].m4 = tmp4; | |||||
| } | |||||
| else | |||||
| { | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| this->m_data[this->m_count].m4 = m4; | |||||
| } | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| void Remove(int pos, int count) | |||||
| template<typename T1, typename T2, typename T3> | |||||
| class Array<T1, T2, T3, void, void, void, void, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, T3, void, void, void, void, void> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2, T3 const &m3) | |||||
| { | { | ||||
| memmove(m_data + pos, m_data + pos + count, m_count - pos - count); | |||||
| m_count -= count; | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; T3 tmp3 = m3; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| this->m_data[this->m_count].m3 = tmp3; | |||||
| } | |||||
| else | |||||
| { | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| this->m_data[this->m_count].m3 = m3; | |||||
| } | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| void Reserve(int count) | |||||
| template<typename T1, typename T2> | |||||
| class Array<T1, T2, void, void, void, void, void, void> | |||||
| : public ArrayBase<ArrayElement<T1, T2, void, void, void, void, void, void> > | |||||
| { | |||||
| public: | |||||
| inline void Append(T1 const &m1, T2 const &m2) | |||||
| { | { | ||||
| if (count <= (int)m_reserved) | |||||
| return; | |||||
| Element *tmp = new Element[count]; | |||||
| if (m_data) | |||||
| if (this->m_count >= this->m_reserved) | |||||
| { | { | ||||
| memcpy(tmp, m_data, m_count * sizeof(Element)); | |||||
| delete[] m_data; | |||||
| T1 tmp1 = m1; T2 tmp2 = m2; | |||||
| Reserve(this->m_count * 13 / 8 + 8); | |||||
| this->m_data[this->m_count].m1 = tmp1; | |||||
| this->m_data[this->m_count].m2 = tmp2; | |||||
| } | } | ||||
| m_data = tmp; | |||||
| m_reserved = count; | |||||
| else | |||||
| { | |||||
| this->m_data[this->m_count].m1 = m1; | |||||
| this->m_data[this->m_count].m2 = m2; | |||||
| } | |||||
| ++this->m_count; | |||||
| } | } | ||||
| }; | |||||
| inline int Count() const { return m_count; } | |||||
| inline int Bytes() const { return m_count * sizeof(Element); } | |||||
| private: | |||||
| Element *m_data; | |||||
| int m_count, m_reserved; | |||||
| template<typename T> | |||||
| class Array<T, void, void, void, void, void, void, void> : public ArrayBase<T> | |||||
| { | |||||
| }; | }; | ||||
| } /* namespace lol */ | } /* namespace lol */ | ||||