stack.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined(INCLUDED_CONTAINER_STACK_H)
00023 #define INCLUDED_CONTAINER_STACK_H
00024 
00025 #include "memory/allocator.h"
00026 #include <algorithm>
00027 
00036 template<typename Type>
00037 class Stack: public DefaultAllocator<Type>
00038 {
00039         typedef DefaultAllocator<Type> Allocator;
00040 
00041         enum
00042         {
00043             DEFAULT_CAPACITY = 4,
00044         };
00045 
00046         typedef Type* pointer;
00047         typedef const Type* const_pointer;
00048 
00049     public:
00050         typedef const_pointer const_iterator;
00051     private:
00052 
00053         pointer m_data;
00054         pointer m_end;
00055         std::size_t m_capacity;
00056 
00057         void insert (const Type& value)
00058         {
00059             Allocator::construct(m_end++, value);
00060         }
00061         void insert_overflow (const Type& value)
00062         {
00063             const std::size_t new_capacity = (m_capacity) ? m_capacity + m_capacity : std::size_t(DEFAULT_CAPACITY);
00064             const pointer new_data = Allocator::allocate(new_capacity);
00065             const pointer new_end = std::copy(m_data, m_end, new_data);
00066 
00067             destroy();
00068             Allocator::deallocate(m_data, m_capacity);
00069 
00070             m_capacity = new_capacity;
00071             m_data = new_data;
00072             m_end = new_end;
00073             insert(value);
00074         }
00075         void destroy ()
00076         {
00077             for (pointer p = m_data; p != m_end; ++p) {
00078                 Allocator::destroy(p);
00079             }
00080         }
00081         void construct (const Stack& other)
00082         {
00083             pointer p = m_data;
00084             for (const_iterator i = other.begin(); i != other.end(); ++i) {
00085                 Allocator::construct(p++, *i);
00086             }
00087         }
00088 
00089     public:
00090 
00091         Stack () :
00092             m_data(0), m_end(0), m_capacity(0)
00093         {
00094         }
00095         Stack (const Type& value) :
00096             m_data(0), m_end(0), m_capacity(0)
00097         {
00098             push(value);
00099         }
00100         Stack (const Stack& other) :
00101             DefaultAllocator<Type> (other)
00102         {
00103             m_capacity = other.m_capacity;
00104             m_data = Allocator::allocate(m_capacity);
00105             construct(other);
00106             m_end = m_data + other.size();
00107         }
00108         ~Stack ()
00109         {
00110             destroy();
00111             Allocator::deallocate(m_data, m_capacity);
00112         }
00113 
00114         const_iterator begin () const
00115         {
00116             return m_data;
00117         }
00118         const_iterator end () const
00119         {
00120             return m_end;
00121         }
00122 
00123         bool empty () const
00124         {
00125             return end() == begin();
00126         }
00127         void clear ()
00128         {
00129             destroy();
00130             m_end = m_data;
00131         }
00132 
00133         std::size_t size () const
00134         {
00135             return m_end - m_data;
00136         }
00137         Type operator[] (const std::size_t i) const
00138         {
00139             return m_data[i];
00140         }
00142         void push (const Type& value)
00143         {
00144             if (size() == m_capacity) {
00145                 insert_overflow(value);
00146             } else {
00147                 insert(value);
00148             }
00149         }
00151         void pop ()
00152         {
00153             Allocator::destroy(--m_end);
00154         }
00156         Type& top ()
00157         {
00158             return *(m_end - 1);
00159         }
00161         const Type& top () const
00162         {
00163             return *(m_end - 1);
00164         }
00166         Type& parent ()
00167         {
00168             return *(m_end - 2);
00169         }
00171         const Type& parent () const
00172         {
00173             return *(m_end - 2);
00174         }
00176         void swap (Stack& other)
00177         {
00178             std::swap(m_data, other.m_data);
00179             std::swap(m_end, other.m_end);
00180             std::swap(m_capacity, other.m_capacity);
00181         }
00182 #if 1 // use copy-swap technique
00183         Stack& operator= (const Stack& other)
00184         {
00185             Stack temp(other);
00186             temp.swap(*this);
00187             return *this;
00188         }
00189 #else // avoids memory allocation if capacity is already sufficient.
00190         Stack& operator=(const Stack& other) {
00191             if (&other != this) {
00192                 destroy();
00193 
00194                 if (other.size() > m_capacity) {
00195                     Allocator::deallocate(m_data, m_capacity);
00196                     m_capacity = other.m_capacity;
00197                     m_data = Allocator::allocate(m_capacity);
00198                 }
00199                 m_end = m_data + other.size();
00200 
00201                 construct(other);
00202             }
00203             return *this;
00204         }
00205 #endif
00206 };
00207 
00209 template<typename Type>
00210 inline bool operator< (const Stack<Type>& self, const Stack<Type>& other)
00211 {
00212     return std::lexicographical_compare(self.begin(), self.end(), other.begin(), other.end());
00213 }
00214 
00215 namespace std
00216 {
00219     template<typename Type>
00220     inline void swap (Stack<Type>& self, Stack<Type>& other)
00221     {
00222         self.swap(other);
00223     }
00224 }
00225 
00226 #endif

Generated by  doxygen 1.6.2