Browse Source

Added linked list class.

Lasse Öörni 14 years ago
parent
commit
088a84a8b8

+ 1 - 5
Engine/Container/Iterator.h

@@ -26,8 +26,6 @@
 /// Random access iterator
 template <class T> class RandomAccessIterator
 {
-    template <class T> friend class RandomAccessConstIterator;
-    
 public:
     /// Construct
     explicit RandomAccessIterator(T* ptr) :
@@ -65,8 +63,7 @@ public:
     bool operator < (const RandomAccessIterator& rhs) const { return ptr_ < rhs.ptr_; }
     /// Test for greater than with another iterator
     bool operator > (const RandomAccessIterator& rhs) const { return ptr_ > rhs.ptr_; }
-
-protected:
+    
     /// Pointer
     T* ptr_;
 };
@@ -120,7 +117,6 @@ public:
     /// Test for greater than with another iterator
     bool operator > (const RandomAccessConstIterator& rhs) const { return ptr_ > rhs.ptr_; }
     
-protected:
     /// Pointer
     T* ptr_;
 };

+ 331 - 0
Engine/Container/List.h

@@ -0,0 +1,331 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "ListBase.h"
+
+/// Linked list template class
+template <class T> class List : public ListBase
+{
+public:
+    /// List node
+    struct Node : public ListNodeBase
+    {
+        /// Construct undefined
+        Node()
+        {
+        }
+        
+        /// Construct with value
+        Node(const T& value) :
+            value_(value)
+        {
+        }
+        
+        /// Node value
+        T value_;
+        
+        /// Return next node
+        Node* GetNext() const { return static_cast<Node*>(next_); }
+        
+        /// Return previous node
+        Node* GetPrev() { return static_cast<Node*>(prev_); }
+    };
+    
+    /// List node iterator
+    class Iterator : public ListIteratorBase
+    {
+    public:
+        /// Construct
+        explicit Iterator(Node* ptr) :
+            ListIteratorBase(ptr)
+        {
+        }
+        
+        /// Preincrement the pointer
+        Iterator& operator ++ () { GotoNext(); return *this; }
+        /// Postincrement the pointer
+        Iterator operator ++ (int) { Iterator it = *this; GotoNext(); return it; }
+        /// Predecrement the pointer
+        Iterator& operator -- () { GotoPrev(); return *this; }
+        /// Postdecrement the pointer
+        Iterator operator -- (int) { Iterator it = *this; GotoPrev(); return it; }
+        
+        /// Point to the node value
+        T* operator -> () const { return &(static_cast<Node*>(ptr_))->value_; }
+        /// Dereference the node value
+        T& operator * () const { return (static_cast<Node*>(ptr_))->value_; }
+    };
+    
+    /// List node const iterator
+    class ConstIterator : public ListIteratorBase
+    {
+    public:
+        /// Construct
+        explicit ConstIterator(Node* ptr) :
+            ListIteratorBase(ptr)
+        {
+        }
+        
+        /// Construct from a non-const iterator
+        ConstIterator(const Iterator& rhs) :
+            ListIteratorBase(rhs.ptr_)
+        {
+        }
+        
+        /// Assign from a non-const iterator
+        ConstIterator& operator = (const Iterator& rhs) { ptr_ = rhs.ptr_; return *this; }
+        /// Preincrement the pointer
+        ConstIterator& operator ++ () { GotoNext(); return *this; }
+        /// Postincrement the pointer
+        ConstIterator operator ++ (int) { Iterator it = *this; GotoNext(); return it; }
+        /// Predecrement the pointer
+        ConstIterator& operator -- () { GotoPrev(); return *this; }
+        /// Postdecrement the pointer
+        ConstIterator operator -- (int) { Iterator it = *this; GotoPrev(); return it; }
+        
+        /// Point to the node value
+        const T* operator -> () const { return &(static_cast<Node*>(ptr_))->value_; }
+        /// Dereference the node value
+        const T& operator * () const { return (static_cast<Node*>(ptr_))->value_; }
+    };
+
+    /// Construct empty
+    List() :
+        ListBase()
+    {
+        // Allocate and link the head and tail nodes
+        head_ = new Node();
+        tail_ = new Node();
+        Node* head = GetHead();
+        Node* tail = GetTail();
+        head->next_ = tail;
+        tail->prev_ = head;
+    }
+    
+    /// Construct from another list
+    List(const List<T>& list) :
+        ListBase()
+    {
+        // Allocate and link the head and tail nodes
+        head_ = new Node();
+        tail_ = new Node();
+        Node* head = GetHead();
+        Node* tail = GetTail();
+        head->next_ = tail;
+        tail->prev_ = head;
+        
+        // Then assign the other list
+        *this = list;
+    }
+    
+    /// Destruct
+    ~List()
+    {
+        Clear();
+        delete GetHead();
+        delete GetTail();
+    }
+    
+    /// Assign from another list
+    List& operator = (const List<T>& rhs)
+    {
+        // Clear, then insert the nodes of the other list
+        Clear();
+        Insert(End(), rhs.Begin(), rhs.End());
+        
+        return *this;
+    }
+    
+    /// Add-assign a value
+    List& operator += (const T& rhs)
+    {
+        Push(rhs);
+        return *this;
+    }
+    
+    /// Add-assign a list
+    List& operator += (const List<T>& rhs)
+    {
+        Insert(End(), rhs.Begin(), rhs.End());
+        return *this;
+    }
+    
+    /// Test for equality with another list
+    bool operator == (const List<T>& rhs) const
+    {
+        if (rhs.size_ != size_)
+            return false;
+        
+        ConstIterator i = Begin();
+        ConstIterator j = rhs.Begin();
+        while (i != End())
+        {
+            if (*i != *j)
+                return false;
+            ++i;
+            ++j;
+        }
+        
+        return true;
+    }
+    
+    /// Test for inequality with another list
+    bool operator != (const List<T>& rhs) const
+    {
+        if (rhs.size_ != size_)
+            return true;
+        
+        ConstIterator i = Begin();
+        ConstIterator j = rhs.Begin();
+        while (i != End())
+        {
+            if (*i != *j)
+                return true;
+            ++i;
+            ++j;
+        }
+        
+        return false;
+    }
+    
+    /// Insert a value at the end
+    void Push(const T& value)
+    {
+        InsertNode(GetTail(), value);
+    }
+    
+    /// Insert a value into the list
+    void Insert(const Iterator& dest, const T& value)
+    {
+        InsertNode(static_cast<Node*>(dest.ptr_), value);
+    }
+    
+    /// Insert a range by iterators
+    void Insert(const Iterator& dest, const Iterator& start, const Iterator& end)
+    {
+        Node* destNode = static_cast<Node*>(dest.ptr_);
+        Iterator it = start;
+        while (it != end)
+        {
+            Iterator current = it++;
+            InsertNode(destNode, *it);
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
+        }
+    }
+    
+    /// Erase the last node
+    void Pop()
+    {
+        if (size_)
+            Erase(End() - 1);
+    }
+    
+    /// Erase a node from the list. Return an iterator to the next element
+    Iterator Erase(Iterator it)
+    {
+        Iterator current = it++;
+        EraseNode(static_cast<Node*>(current.ptr_));
+        
+        return it;
+    }
+    
+    /// Erase a range of nodes from the list. Return an iterator to the next element
+    Iterator Erase(const Iterator& start, const Iterator& end)
+    {
+        Iterator it = start;
+        while (it != end)
+        {
+            Iterator current = it++;
+            // Break if the iterator got stuck
+            if (it == current)
+                break;
+            EraseNode(static_cast<Node*>(current.ptr_));
+        }
+        
+        return it;
+    }
+    
+    /// Clear the list
+    void Clear()
+    {
+        while (size_)
+            EraseNode(GetTail()->GetPrev());
+    }
+    
+    /// Return iterator to the first actual node
+    Iterator Begin() { return Iterator(GetHead()->GetNext()); }
+    /// Return iterator to the first actual node
+    ConstIterator Begin() const { return ConstIterator(GetHead()->GetNext()); }
+    /// Return iterator to the end
+    Iterator End() { return Iterator(GetTail()); }
+    /// Return iterator to the end
+    ConstIterator End() const { return ConstIterator(GetTail()); }
+    /// Return first value
+    const T& Front() const { return *Begin(); }
+    /// Return last value
+    const T& Back() const { return *(--End()); }
+    /// Return number of value
+    unsigned Size() const { return size_; }
+    /// Return whether list is empty
+    bool Empty() const { return size_ == 0; }
+    
+private:
+    /// Return the head pointer with correct type
+    Node* GetHead() const { return reinterpret_cast<Node*>(head_); }
+    /// Return the tail pointer with correct type
+    Node* GetTail() const { return reinterpret_cast<Node*>(tail_); }
+    
+    /// Insert a value into the list
+    void InsertNode(Node* dest, const T& value)
+    {
+        // The head node can not be replaced
+        if ((!dest) || (dest == head_))
+            return;
+        
+        Node* newNode = new Node(value);
+        newNode->next_ = dest;
+        newNode->prev_ = dest->prev_;
+        dest->prev_ = newNode;
+        ++size_;
+    }
+    
+    /// Erase a node from the list
+    void EraseNode(Node* toRemove)
+    {
+        // The head or tail can not be removed
+        if ((!toRemove) || (toRemove == head_) || (toRemove == tail_))
+            return;
+        
+        /// \todo Should check that the node belongs to the list
+        Node* prev = toRemove->GetPrev();
+        Node* next = toRemove->GetNext();
+        prev->next_ = next;
+        next->prev_ = prev;
+        delete toRemove;
+        --size_;
+    }
+};

+ 26 - 1
Engine/Container/ListBase.h

@@ -56,7 +56,6 @@ public:
     /// Test for inequality with another iterator
     bool operator != (const ListIteratorBase& rhs) const { return ptr_ != rhs.ptr_; }
     
-protected:
     /// Go to the next node
     void GotoNext()
     {
@@ -75,6 +74,32 @@ protected:
     ListNodeBase* ptr_;
 };
 
+/// Linked list base class
+class ListBase
+{
+public:
+    ListBase() :
+        size_(0)
+    {
+    }
+    
+    /// Swap with another linked list
+    void Swap(ListBase& rhs)
+    {
+        ::Swap(head_, rhs.head_);
+        ::Swap(tail_, rhs.tail_);
+        ::Swap(size_, rhs.size_);
+    }
+    
+protected:
+    /// Head node pointer
+    ListNodeBase* head_;
+    /// Tail node pointer
+    ListNodeBase* tail_;
+    /// Number of nodes
+    unsigned size_;
+};
+
 /// Skip list node base
 struct SkipListNodeBase : public ListNodeBase
 {

+ 6 - 8
Engine/Container/Map.h

@@ -82,8 +82,6 @@ public:
     /// Map node iterator
     class Iterator : public ListIteratorBase
     {
-        friend class ConstIterator;
-        
     public:
         /// Construct
         explicit Iterator(Node* ptr) :
@@ -144,8 +142,8 @@ public:
         SkipListBase(maxHeight)
     {
         // Allocate the head and tail nodes and zero the next pointers
-        head_ = AllocateNode(maxHeight_, T());
-        tail_ = AllocateNode(maxHeight_, T());
+        head_ = AllocateNode(maxHeight_);
+        tail_ = AllocateNode(maxHeight_);
         Node* head = GetHead();
         Node* tail = GetTail();
         for (unsigned i = 0; i < maxHeight_; ++i)
@@ -163,8 +161,8 @@ public:
         SkipListBase(map.maxHeight_)
     {
         // Allocate the head and tail nodes and zero the next pointers
-        head_ = AllocateNode(maxHeight_, T());
-        tail_ = AllocateNode(maxHeight_, T());
+        head_ = AllocateNode(maxHeight_);
+        tail_ = AllocateNode(maxHeight_);
         Node* head = GetHead();
         Node* tail = GetTail();
         for (unsigned i = 0; i < maxHeight_; ++i)
@@ -176,7 +174,7 @@ public:
         // Allocate the fixup pointers
         fix_ = reinterpret_cast<void**>(new Node*[maxHeight_]);
         
-        // Then assign the another map
+        // Then assign the other map
         *this = map;
     }
     
@@ -518,7 +516,7 @@ private:
     }
     
     /// Allocate a node and its next pointers
-    Node* AllocateNode(unsigned height, const T& key)
+    Node* AllocateNode(unsigned height, const T& key = T())
     {
         unsigned char* block = new unsigned char[sizeof(Node) + (height - 1) * sizeof(Node*)];
         Node* newNode = reinterpret_cast<Node*>(block);

+ 2 - 4
Engine/Container/Set.h

@@ -55,8 +55,6 @@ public:
     /// Set node iterator
     class Iterator : public ListIteratorBase
     {
-        friend class ConstIterator;
-        
     public:
         /// Construct
         explicit Iterator(Node* ptr) :
@@ -149,7 +147,7 @@ public:
         // Allocate the fixup pointers
         fix_ = reinterpret_cast<void**>(new Node*[maxHeight_]);
         
-        // Then assign the another set
+        // Then assign the other set
         *this = set;
     }
     
@@ -236,7 +234,7 @@ public:
     void Insert(const Iterator& start, const Iterator& end)
     {
         Iterator it = start;
-        while ((it) && (it != end))
+        while (it != end)
         {
             Iterator current = it++;
             Insert(*current);

+ 5 - 0
Engine/Container/Swap.cpp

@@ -35,6 +35,11 @@ template<> void Swap<VectorBase>(VectorBase& first, VectorBase& second)
     first.Swap(second);
 }
 
+template<> void Swap<ListBase>(ListBase& first, ListBase& second)
+{
+    first.Swap(second);
+}
+
 template<> void Swap<SkipListBase>(SkipListBase& first, SkipListBase& second)
 {
     first.Swap(second);

+ 2 - 0
Engine/Container/Swap.h

@@ -23,6 +23,7 @@
 
 #pragma once
 
+class ListBase;
 class SkipListBase;
 class String;
 class VectorBase;
@@ -37,4 +38,5 @@ template<class T> inline void Swap(T& first, T& second)
 
 template<> void Swap<String>(String& first, String& second);
 template<> void Swap<VectorBase>(VectorBase& first, VectorBase& second);
+template<> void Swap<ListBase>(ListBase& first, ListBase& second);
 template<> void Swap<SkipListBase>(SkipListBase& first, SkipListBase& second);

+ 28 - 19
Tools/ShaderCompiler/ShaderCompiler.cpp

@@ -28,8 +28,8 @@
 #include "StringUtils.h"
 #include "XMLFile.h"
 
+#include <cstdio>
 #include <cstring>
-#include <map>
 
 #include "DebugNew.h"
 
@@ -333,43 +333,52 @@ void Run(const Vector<String>& arguments)
             // Add global parameter & texture sampler definitions
             {
                 XMLElement parameters = outShaders.CreateChildElement("vsparameters");
-                std::multimap<unsigned, String> sorted;
+                Map<unsigned, Vector<String> > sorted;
                 for (Map<String, unsigned>::ConstIterator i = vsParams_.Begin(); i != vsParams_.End(); ++i)
-                    sorted.insert(std::pair<unsigned, String>(i->second_, i->first_));
+                    sorted[i->second_].Push(i->first_);
                 
-                for (std::multimap<unsigned, String>::const_iterator i = sorted.begin(); i != sorted.end(); ++i)
+                for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
                 {
-                    XMLElement param = parameters.CreateChildElement("parameter");
-                    param.SetString("name", i->second);
-                    param.SetString("index", ToString(i->first));
+                    for (unsigned j = 0; j < i->second_.Size(); ++j)
+                    {
+                        XMLElement param = parameters.CreateChildElement("parameter");
+                        param.SetString("name", i->second_[j]);
+                        param.SetString("index", ToString(i->first_));
+                    }
                 }
             }
             
             {
                 XMLElement parameters = outShaders.CreateChildElement("psparameters");
-                std::multimap<unsigned, String> sorted;
+                Map<unsigned, Vector<String> > sorted;
                 for (Map<String, unsigned>::ConstIterator i = psParams_.Begin(); i != psParams_.End(); ++i)
-                    sorted.insert(std::pair<unsigned, String>(i->second_, i->first_));
+                    sorted[i->second_].Push(i->first_);
                 
-                for (std::multimap<unsigned, String>::const_iterator i = sorted.begin(); i != sorted.end(); ++i)
+                for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
                 {
-                    XMLElement param = parameters.CreateChildElement("parameter");
-                    param.SetString("name", i->second);
-                    param.SetString("index", ToString(i->first));
+                    for (unsigned j = 0; j < i->second_.Size(); ++j)
+                    {
+                        XMLElement param = parameters.CreateChildElement("parameter");
+                        param.SetString("name", i->second_[j]);
+                        param.SetString("index", ToString(i->first_));
+                    }
                 }
             }
             
             {
                 XMLElement parameters = outShaders.CreateChildElement("textureunits");
-                std::multimap<unsigned, String> sorted;
+                Map<unsigned, Vector<String> > sorted;
                 for (Map<String, unsigned>::ConstIterator i = textureUnits_.Begin(); i != textureUnits_.End(); ++i)
-                    sorted.insert(std::pair<unsigned, String>(i->second_, i->first_));
+                    sorted[i->second_].Push(i->first_);
                 
-                for (std::multimap<unsigned, String>::const_iterator i = sorted.begin(); i != sorted.end(); ++i)
+                for (Map<unsigned, Vector<String> >::ConstIterator i = sorted.Begin(); i != sorted.End(); ++i)
                 {
-                    XMLElement param = parameters.CreateChildElement("textureunit");
-                    param.SetString("name", i->second);
-                    param.SetString("index", ToString(i->first));
+                    for (unsigned j = 0; j < i->second_.Size(); ++j)
+                    {
+                        XMLElement param = parameters.CreateChildElement("parameter");
+                        param.SetString("name", i->second_[j]);
+                        param.SetString("index", ToString(i->first_));
+                    }
                 }
             }