smallstack_type.hpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef SMALLSTACK_TYPE_HPP
00013 #define SMALLSTACK_TYPE_HPP
00014 
00015 #include "pool_type.hpp"
00016 #include "pool_func.hpp"
00017 
00022 template <typename Tindex, typename Titem>
00023 class SmallStackItem {
00024 protected:
00025   Tindex next; 
00026   Titem value; 
00027 
00033   inline SmallStackItem(const Titem &value, Tindex next) :
00034     next(next), value(value) {}
00035 };
00036 
00059 template <typename Titem, typename Tindex, Titem Tinvalid, size_t Tgrowth_step, size_t Tmax_size>
00060 class SmallStack : public SmallStackItem<Tindex, Titem> {
00061 protected:
00062   class PooledSmallStack;
00063 
00067   void Branch()
00068   {
00069     if (PooledSmallStack::IsValidID(this->next)) {
00070       PooledSmallStack::Get(this->next)->CreateBranch();
00071     }
00072   }
00073 
00074 public:
00075   typedef SmallStackItem<Tindex, Titem> Item;
00076   typedef Pool<PooledSmallStack, Tindex, Tgrowth_step, Tmax_size, PT_NORMAL, true, false> SmallStackPool;
00077 
00082   inline SmallStack(const Titem &value = Tinvalid) : Item(value, Tmax_size) {}
00083 
00087   inline ~SmallStack()
00088   {
00089     if (PooledSmallStack::IsValidID(this->next)) {
00090       PooledSmallStack *item = PooledSmallStack::Get(this->next);
00091       if (item->NumBranches() == 0) {
00092         delete item;
00093       } else {
00094         item->DeleteBranch();
00095       }
00096     }
00097   }
00098 
00103   inline SmallStack(const SmallStack &other) : Item(other) { this->Branch(); }
00104 
00110   inline SmallStack &operator=(const SmallStack &other)
00111   {
00112     if (this == &other) return *this;
00113     this->~SmallStack();
00114     this->next = other.next;
00115     this->value = other.value;
00116     this->Branch();
00117     return *this;
00118   }
00119 
00124   inline void Push(const Titem &item)
00125   {
00126     if (this->value != Tinvalid) {
00127       assert(PooledSmallStack::CanAllocateItem());
00128       PooledSmallStack *next = new PooledSmallStack(this->value, this->next);
00129       this->next = next->index;
00130     }
00131     this->value = item;
00132   }
00133 
00138   inline Titem Pop()
00139   {
00140     Titem ret = this->value;
00141     if (!PooledSmallStack::IsValidID(this->next)) {
00142       this->value = Tinvalid;
00143     } else {
00144       PooledSmallStack *next = PooledSmallStack::Get(this->next);
00145       static_cast<Item &>(*this) = *next;
00146       if (next->NumBranches() == 0) {
00147         delete next;
00148       } else {
00149         next->DeleteBranch();
00150         this->Branch();
00151       }
00152     }
00153     return ret;
00154   }
00155 
00160   inline bool IsEmpty() const
00161   {
00162     return this->value == Tinvalid && !PooledSmallStack::IsValidID(this->next);
00163   }
00164 
00170   inline bool Contains(const Titem &item) const
00171   {
00172     if (item == Tinvalid || item == this->value) return true;
00173     const SmallStack *in_list = this;
00174     while (PooledSmallStack::IsValidID(in_list->next)) {
00175       in_list = static_cast<const SmallStack *>(
00176           static_cast<const Item *>(PooledSmallStack::Get(in_list->next)));
00177       if (in_list->value == item) return true;
00178     }
00179     return false;
00180   }
00181 
00182 protected:
00183   static SmallStackPool _pool;
00184 
00188   class PooledSmallStack : public Item, public SmallStackPool::template PoolItem<&SmallStack::_pool> {
00189   private:
00190     Tindex branch_count; 
00191   public:
00192     PooledSmallStack(Titem value, Tindex next) : Item(value, next), branch_count(0) {}
00193 
00194     inline void CreateBranch() { ++this->branch_count; }
00195     inline void DeleteBranch() { --this->branch_count; }
00196     inline Tindex NumBranches() { return this->branch_count; }
00197   };
00198 };
00199 
00200 
00201 #endif