| @@ -11,7 +11,8 @@ | |||
| // | |||
| // 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__ | |||
| @@ -22,22 +23,27 @@ | |||
| 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: | |||
| 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); | |||
| memcpy(m_data, that.m_data, m_count * sizeof(Element)); | |||
| m_count = that.m_count; | |||
| } | |||
| Array& operator=(Array const& that) | |||
| ArrayBase& operator=(ArrayBase const& that) | |||
| { | |||
| m_data = 0; | |||
| m_count = 0; | |||
| @@ -58,38 +64,24 @@ public: | |||
| 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) | |||
| { | |||
| /* 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); | |||
| m_data[m_count++] = tmp; | |||
| } | |||
| else | |||
| { | |||
| m_data[m_count++] = x; | |||
| } | |||
| 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) | |||
| @@ -122,203 +114,289 @@ public: | |||
| inline int Count() const { return m_count; } | |||
| inline int Bytes() const { return m_count * sizeof(Element); } | |||
| private: | |||
| protected: | |||
| Element *m_data; | |||
| 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: | |||
| 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 | |||
| 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 | |||
| { | |||
| 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: | |||
| 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 | |||
| { | |||
| 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 */ | |||