Jelajahi Sumber

Add Vector type support.

Aster Jian 12 tahun lalu
induk
melakukan
7f15f788e6
1 mengubah file dengan 407 tambahan dan 0 penghapusan
  1. 407 0
      Extras/LuaScript/Pkgs/Container/Vector.pkg

+ 407 - 0
Extras/LuaScript/Pkgs/Container/Vector.pkg

@@ -0,0 +1,407 @@
+$#include "Vector.h"
+
+/// %Vector template class.
+class Vector : public VectorBase
+{
+	TOLUA_TEMMPLATE_BIND(T, String)
+public:
+    /// Construct empty.
+    Vector()
+    {
+    }
+    
+    /// Construct with initial size.
+    explicit Vector(unsigned size)
+    {
+        Resize(size, 0);
+    }
+    
+    /// Construct with initial data.
+    Vector(const T* data, unsigned size)
+    {
+        Resize(size, data);
+    }
+    
+    /// Construct from another vector.
+    Vector(const Vector<T>& vector)
+    {
+        *this = vector;
+    }
+    
+    /// Destruct.
+    ~Vector()
+    {
+        Clear();
+        delete[] buffer_;
+    }
+    
+    /// Add an element.
+    Vector<T> operator + (const T& rhs) const
+    {
+        Vector<T> ret(*this);
+        ret.Push(rhs);
+        return ret;
+    }
+    
+    /// Add another vector.
+    Vector<T> operator + (const Vector<T>& rhs) const
+    {
+        Vector<T> ret(*this);
+        ret.Push(rhs);
+        return ret;
+    }
+    
+    /// Test for equality with another vector.
+    bool operator == (const Vector<T>& rhs) const
+    {
+        if (rhs.size_ != size_)
+            return false;
+        
+        T* buffer = Buffer();
+        T* rhsBuffer = rhs.Buffer();
+        for (unsigned i = 0; i < size_; ++i)
+        {
+            if (buffer[i] != rhsBuffer[i])
+                return false;
+        }
+        
+        return true;
+    }
+    
+    /// Return element at index.
+    T& operator [] (unsigned index) { assert(index < size_); return Buffer()[index]; }
+    /// Return const element at index.
+    const T& operator [] (unsigned index) const { assert(index < size_); return Buffer()[index]; }
+    /// Return element at index.
+    T& At(unsigned index) { assert(index < size_); return Buffer()[index]; }
+    /// Return const element at index.
+    const T& At(unsigned index) const { assert(index < size_); return Buffer()[index]; }
+
+    /// Add an element at the end.
+    void Push(const T& value) { Resize(size_ + 1, &value); }
+    /// Add another vector at the end.
+    void Push(const Vector<T>& vector) { Resize(size_ + vector.size_, vector.Buffer()); }
+    
+    /// Remove the last element.
+    void Pop()
+    {
+        if (size_)
+            Resize(size_ - 1, 0);
+    }
+    
+    /// Insert an element at position.
+    void Insert(unsigned pos, const T& value)
+    {
+        if (pos > size_)
+            pos = size_;
+        
+        unsigned oldSize = size_;
+        Resize(size_ + 1, 0);
+        MoveRange(pos + 1, pos, oldSize - pos);
+        Buffer()[pos] = value;
+    }
+    
+    /// Insert another vector at position.
+    void Insert(unsigned pos, const Vector<T>& vector)
+    {
+        if (pos > size_)
+            pos = size_;
+        
+        unsigned oldSize = size_;
+        Resize(size_ + vector.size_, 0);
+        MoveRange(pos + vector.size_, pos, oldSize - pos);
+        CopyElements(Buffer() + pos, vector.Buffer(), vector.size_);
+    }
+    /// Erase a range of elements.
+    void Erase(unsigned pos, unsigned length = 1)
+    {
+        // Return if the range is illegal
+        if (pos + length > size_ || !length)
+            return;
+        
+        MoveRange(pos, pos + length, size_ - pos - length);
+        Resize(size_ - length, 0);
+    }
+       
+	/// Erase an element if found.
+    bool Remove(const T& value)
+    {
+        Iterator i = Find(value);
+        if (i != End())
+        {
+            Erase(i);
+            return true;
+        }
+        else
+            return false;
+    }
+    
+    /// Clear the vector.
+    void Clear() { Resize(0); }
+    /// Resize the vector.
+    void Resize(unsigned newSize) { Resize(newSize, 0); }
+    
+    /// Set new capacity.
+    void Reserve(unsigned newCapacity)
+    {
+        if (newCapacity < size_)
+            newCapacity = size_;
+        
+        if (newCapacity != capacity_)
+        {
+            T* newBuffer = 0;
+            capacity_ = newCapacity;
+            
+            if (capacity_)
+            {
+                newBuffer = reinterpret_cast<T*>(AllocateBuffer(capacity_ * sizeof(T)));
+                // Move the data into the new buffer
+                ConstructElements(newBuffer, Buffer(), size_);
+            }
+            
+            // Delete the old buffer
+            DestructElements(Buffer(), size_);
+            delete[] buffer_;
+            buffer_ = reinterpret_cast<unsigned char*>(newBuffer);
+        }
+    }
+    
+    /// Reallocate so that no extra memory is used.
+    void Compact() { Reserve(size_); }
+    
+    /// Return whether contains a specific value.
+    bool Contains(const T& value) const { return Find(value) != End(); }
+    
+    /// Return first element.
+    T& Front() { assert(size_); return Buffer()[0]; }
+    /// Return const first element.
+    const T& Front() const { assert(size_); return Buffer()[0]; }
+    /// Return last element.
+    T& Back() { assert(size_); return Buffer()[size_ - 1]; }
+    /// Return const last element.
+    const T& Back() const { assert(size_); return Buffer()[size_ - 1]; }
+    /// Return size of vector.
+    unsigned Size() const { return size_; }
+    /// Return capacity of vector.
+    unsigned Capacity() const { return capacity_; }
+    /// Return whether vector is empty.
+    bool Empty() const { return size_ == 0; }    
+};
+
+/// %Vector template class for POD types. Does not call constructors or destructors and uses block move.
+class PODVector
+{
+	TOLUA_TEMPLATE_BIND(T, Vector3)
+public:   
+    /// Construct empty.
+    PODVector()
+    {
+    }
+    
+    /// Construct with initial size.
+    explicit PODVector(unsigned size)
+    {
+        Resize(size);
+    }
+    
+    /// Construct with initial data.
+    PODVector(const T* data, unsigned size)
+    {
+        Resize(size);
+        CopyElements(Buffer(), data, size);
+    }
+    
+    /// Destruct.
+    ~PODVector()
+    {
+        delete[] buffer_;
+    }
+    
+    /// Add an element.
+    PODVector<T> operator + (const T& rhs) const
+    {
+        PODVector<T> ret(*this);
+        ret.Push(rhs);
+        return ret;
+    }
+    
+    /// Add another vector.
+    PODVector<T> operator + (const PODVector<T>& rhs) const
+    {
+        PODVector<T> ret(*this);
+        ret.Push(rhs);
+        return ret;
+    }
+    
+    /// Test for equality with another vector.
+    bool operator == (const PODVector<T>& rhs) const
+    {
+        if (rhs.size_ != size_)
+            return false;
+        
+        T* buffer = Buffer();
+        T* rhsBuffer = rhs.Buffer();
+        for (unsigned i = 0; i < size_; ++i)
+        {
+            if (buffer[i] != rhsBuffer[i])
+                return false;
+        }
+        
+        return true;
+    }
+    
+    /// Return element at index.
+    T& operator [] (unsigned index) { assert(index < size_); return Buffer()[index]; }
+    /// Return const element at index.
+    const T& operator [] (unsigned index) const { assert(index < size_); return Buffer()[index]; }
+    /// Return element at index.
+    T& At(unsigned index) { assert(index < size_); return Buffer()[index]; }
+    /// Return const element at index.
+    const T& At(unsigned index) const { assert(index < size_); return Buffer()[index]; }
+    
+    /// Add an element at the end.
+    void Push(const T& value)
+    {
+        if (size_ < capacity_)
+            ++size_;
+        else
+            Resize(size_ + 1);
+        Back() = value;
+    }
+    
+    /// Add another vector at the end.
+    void Push(const PODVector<T>& vector)
+    {
+        unsigned oldSize = size_;
+        Resize(size_ + vector.size_);
+        CopyElements(Buffer() + oldSize, vector.Buffer(), vector.size_);
+    }
+    
+    /// Remove the last element.
+    void Pop()
+    {
+        if (size_)
+            Resize(size_ - 1);
+    }
+    
+    /// Insert an element at position.
+    void Insert(unsigned pos, const T& value)
+    {
+        if (pos > size_)
+            pos = size_;
+        
+        unsigned oldSize = size_;
+        Resize(size_ + 1);
+        MoveRange(pos + 1, pos, oldSize - pos);
+        Buffer()[pos] = value;
+    }
+    
+    /// Insert another vector at position.
+    void Insert(unsigned pos, const PODVector<T>& vector)
+    {
+        if (pos > size_)
+            pos = size_;
+        
+        unsigned oldSize = size_;
+        Resize(size_ + vector.size_);
+        MoveRange(pos + vector.size_, pos, oldSize - pos);
+        CopyElements(Buffer() + pos, vector.Buffer(), vector.size_);
+    }
+    
+    /// Erase a range of elements.
+    void Erase(unsigned pos, unsigned length = 1)
+    {
+        // Return if the range is illegal
+        if (!length || pos + length > size_)
+            return;
+        
+        MoveRange(pos, pos + length, size_ - pos - length);
+        Resize(size_ - length);
+    }
+    
+    /// Erase an element if found.
+    bool Remove(const T& value)
+    {
+        Iterator i = Find(value);
+        if (i != End())
+        {
+            Erase(i);
+            return true;
+        }
+        else
+            return false;
+    }
+    
+    /// Clear the vector.
+    void Clear() { Resize(0); }
+    
+    /// Resize the vector.
+    void Resize(unsigned newSize)
+    {
+        if (newSize > capacity_)
+        {
+            if (!capacity_)
+                capacity_ = newSize;
+            else
+            {
+                while (capacity_ < newSize)
+                    capacity_ += (capacity_ + 1) >> 1;
+            }
+            
+            unsigned char* newBuffer = AllocateBuffer(capacity_ * sizeof(T));
+            // Move the data into the new buffer and delete the old
+            if (buffer_)
+            {
+                CopyElements(reinterpret_cast<T*>(newBuffer), Buffer(), size_);
+                delete[] buffer_;
+            }
+            buffer_ = newBuffer;
+        }
+        
+        size_ = newSize;
+    }
+    
+    /// Set new capacity.
+    void Reserve(unsigned newCapacity)
+    {
+        if (newCapacity < size_)
+            newCapacity = size_;
+        
+        if (newCapacity != capacity_)
+        {
+            unsigned char* newBuffer = 0;
+            capacity_ = newCapacity;
+            
+            if (capacity_)
+            {
+                newBuffer = AllocateBuffer(capacity_ * sizeof(T));
+                // Move the data into the new buffer
+                CopyElements(reinterpret_cast<T*>(newBuffer), Buffer(), size_);
+            }
+            
+            // Delete the old buffer
+            delete[] buffer_;
+            buffer_ = newBuffer;
+        }
+    }
+    
+    /// Reallocate so that no extra memory is used.
+    void Compact() { Reserve(size_); }
+    
+    /// Return whether contains a specific value.
+    bool Contains(const T& value) const { return Find(value) != End(); }
+    /// Return first element.
+    T& Front() { return Buffer()[0]; }
+    /// Return const first element.
+    const T& Front() const { return Buffer()[0]; }
+    /// Return last element.
+    T& Back() { assert(size_); return Buffer()[size_ - 1]; }
+    /// Return const last element.
+    const T& Back() const { assert(size_); return Buffer()[size_ - 1]; }
+    /// Return number of elements.
+    unsigned Size() const { return size_; }
+    /// Return capacity of vector.
+    unsigned Capacity() const { return capacity_; }
+    /// Return whether vector is empty.
+    bool Empty() const { return size_ == 0; }
+};