mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-23 04:12:06 +00:00
fixed eol-style
git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/trunk@23 8a3a26a2-13c4-0310-b231-cf6edde360e5
This commit is contained in:
parent
29ac8a44c6
commit
7f7e598c4a
1 changed files with 239 additions and 239 deletions
|
@ -1,239 +1,239 @@
|
|||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_CONTAINER_STACK_H)
|
||||
#define INCLUDED_CONTAINER_STACK_H
|
||||
|
||||
#include "memory/allocator.h"
|
||||
#include <algorithm>
|
||||
|
||||
/// \brief A stack whose storage capacity is variable at run-time. Similar to std::vector.
|
||||
///
|
||||
/// - Pushing or popping elements is a constant-time operation (on average).
|
||||
/// - The storage capacity of the stack will grow when a new element is added beyond the current capacity. Iterators are invalidated when the storage capacity grows.
|
||||
/// - DefaultConstructible, Copyable, Assignable.
|
||||
/// - Compatible with the containers and algorithms in the Standard Template Library (STL) - http://www.sgi.com/tech/stl/
|
||||
///
|
||||
/// \param Type: The type to be stored in the stack. Must provide a copy-constructor.
|
||||
template<typename Type>
|
||||
class Stack : public DefaultAllocator<Type>
|
||||
{
|
||||
typedef DefaultAllocator<Type> Allocator;
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 4,
|
||||
};
|
||||
|
||||
typedef Type* pointer;
|
||||
typedef const Type* const_pointer;
|
||||
|
||||
public:
|
||||
typedef const_pointer const_iterator;
|
||||
private:
|
||||
|
||||
pointer m_data;
|
||||
pointer m_end;
|
||||
std::size_t m_capacity;
|
||||
|
||||
|
||||
void insert(const Type& value)
|
||||
{
|
||||
Allocator::construct(m_end++, value);
|
||||
}
|
||||
void insert_overflow(const Type& value)
|
||||
{
|
||||
const std::size_t new_capacity = (m_capacity) ? m_capacity + m_capacity : std::size_t(DEFAULT_CAPACITY);
|
||||
const pointer new_data = Allocator::allocate(new_capacity);
|
||||
const pointer new_end = std::copy(m_data, m_end, new_data);
|
||||
|
||||
destroy();
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
|
||||
m_capacity = new_capacity;
|
||||
m_data = new_data;
|
||||
m_end = new_end;
|
||||
insert(value);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
for(pointer p = m_data; p != m_end; ++p)
|
||||
{
|
||||
Allocator::destroy(p);
|
||||
}
|
||||
}
|
||||
void construct(const Stack& other)
|
||||
{
|
||||
pointer p = m_data;
|
||||
for(const_iterator i = other.begin(); i != other.end(); ++i)
|
||||
{
|
||||
Allocator::construct(p++, *i);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Stack() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_capacity(0)
|
||||
{
|
||||
}
|
||||
Stack(const Type& value) :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_capacity(0)
|
||||
{
|
||||
push(value);
|
||||
}
|
||||
Stack(const Stack& other) :
|
||||
DefaultAllocator<Type>(other)
|
||||
{
|
||||
m_capacity = other.m_capacity;
|
||||
m_data = Allocator::allocate(m_capacity);
|
||||
construct(other);
|
||||
m_end = m_data + other.size();
|
||||
}
|
||||
~Stack()
|
||||
{
|
||||
destroy();
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return end() == begin();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
destroy();
|
||||
m_end = m_data;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_end - m_data;
|
||||
}
|
||||
Type operator[](const std::size_t i) const
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
/// \brief Pushes \p value onto the stack at the top element. If reserved storage is insufficient for the new element, this will invalidate all iterators.
|
||||
void push(const Type& value)
|
||||
{
|
||||
if(size() == m_capacity)
|
||||
{
|
||||
insert_overflow(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert(value);
|
||||
}
|
||||
}
|
||||
/// \brief Removes the top element of the stack.
|
||||
void pop()
|
||||
{
|
||||
Allocator::destroy(--m_end);
|
||||
}
|
||||
/// \brief Returns the top element of the mutable stack.
|
||||
Type& top()
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
/// \brief Returns the top element of the non-mutable stack.
|
||||
const Type& top() const
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
/// \brief Returns the element below the top element of the mutable stack.
|
||||
Type& parent()
|
||||
{
|
||||
return *(m_end-2);
|
||||
}
|
||||
/// \brief Returns the element below the top element of the non-mutable stack.
|
||||
const Type& parent() const
|
||||
{
|
||||
return *(m_end-2);
|
||||
}
|
||||
/// \brief Swaps the values of this stack and \p other.
|
||||
void swap(Stack& other)
|
||||
{
|
||||
std::swap(m_data, other.m_data);
|
||||
std::swap(m_end, other.m_end);
|
||||
std::swap(m_capacity, other.m_capacity);
|
||||
}
|
||||
#if 1 // use copy-swap technique
|
||||
Stack& operator=(const Stack& other)
|
||||
{
|
||||
Stack temp(other);
|
||||
temp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#else // avoids memory allocation if capacity is already sufficient.
|
||||
Stack& operator=(const Stack& other)
|
||||
{
|
||||
if(&other != this)
|
||||
{
|
||||
destroy();
|
||||
|
||||
if(other.size() > m_capacity)
|
||||
{
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
m_capacity = other.m_capacity;
|
||||
m_data = Allocator::allocate(m_capacity);
|
||||
}
|
||||
m_end = m_data + other.size();
|
||||
|
||||
construct(other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \brief Returns true if \p self is lexicographically less than \p other.
|
||||
template<typename Type>
|
||||
inline bool operator<(const Stack<Type>& self, const Stack<Type>& other)
|
||||
{
|
||||
return std::lexicographical_compare(self.begin(), self.end(), other.begin(), other.end());
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap().
|
||||
template<typename Type>
|
||||
inline void swap(Stack<Type>& self, Stack<Type>& other)
|
||||
{
|
||||
self.swap(other);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant 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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant 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. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_CONTAINER_STACK_H)
|
||||
#define INCLUDED_CONTAINER_STACK_H
|
||||
|
||||
#include "memory/allocator.h"
|
||||
#include <algorithm>
|
||||
|
||||
/// \brief A stack whose storage capacity is variable at run-time. Similar to std::vector.
|
||||
///
|
||||
/// - Pushing or popping elements is a constant-time operation (on average).
|
||||
/// - The storage capacity of the stack will grow when a new element is added beyond the current capacity. Iterators are invalidated when the storage capacity grows.
|
||||
/// - DefaultConstructible, Copyable, Assignable.
|
||||
/// - Compatible with the containers and algorithms in the Standard Template Library (STL) - http://www.sgi.com/tech/stl/
|
||||
///
|
||||
/// \param Type: The type to be stored in the stack. Must provide a copy-constructor.
|
||||
template<typename Type>
|
||||
class Stack : public DefaultAllocator<Type>
|
||||
{
|
||||
typedef DefaultAllocator<Type> Allocator;
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 4,
|
||||
};
|
||||
|
||||
typedef Type* pointer;
|
||||
typedef const Type* const_pointer;
|
||||
|
||||
public:
|
||||
typedef const_pointer const_iterator;
|
||||
private:
|
||||
|
||||
pointer m_data;
|
||||
pointer m_end;
|
||||
std::size_t m_capacity;
|
||||
|
||||
|
||||
void insert(const Type& value)
|
||||
{
|
||||
Allocator::construct(m_end++, value);
|
||||
}
|
||||
void insert_overflow(const Type& value)
|
||||
{
|
||||
const std::size_t new_capacity = (m_capacity) ? m_capacity + m_capacity : std::size_t(DEFAULT_CAPACITY);
|
||||
const pointer new_data = Allocator::allocate(new_capacity);
|
||||
const pointer new_end = std::copy(m_data, m_end, new_data);
|
||||
|
||||
destroy();
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
|
||||
m_capacity = new_capacity;
|
||||
m_data = new_data;
|
||||
m_end = new_end;
|
||||
insert(value);
|
||||
}
|
||||
void destroy()
|
||||
{
|
||||
for(pointer p = m_data; p != m_end; ++p)
|
||||
{
|
||||
Allocator::destroy(p);
|
||||
}
|
||||
}
|
||||
void construct(const Stack& other)
|
||||
{
|
||||
pointer p = m_data;
|
||||
for(const_iterator i = other.begin(); i != other.end(); ++i)
|
||||
{
|
||||
Allocator::construct(p++, *i);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Stack() :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_capacity(0)
|
||||
{
|
||||
}
|
||||
Stack(const Type& value) :
|
||||
m_data(0),
|
||||
m_end(0),
|
||||
m_capacity(0)
|
||||
{
|
||||
push(value);
|
||||
}
|
||||
Stack(const Stack& other) :
|
||||
DefaultAllocator<Type>(other)
|
||||
{
|
||||
m_capacity = other.m_capacity;
|
||||
m_data = Allocator::allocate(m_capacity);
|
||||
construct(other);
|
||||
m_end = m_data + other.size();
|
||||
}
|
||||
~Stack()
|
||||
{
|
||||
destroy();
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return end() == begin();
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
destroy();
|
||||
m_end = m_data;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_end - m_data;
|
||||
}
|
||||
Type operator[](const std::size_t i) const
|
||||
{
|
||||
return m_data[i];
|
||||
}
|
||||
/// \brief Pushes \p value onto the stack at the top element. If reserved storage is insufficient for the new element, this will invalidate all iterators.
|
||||
void push(const Type& value)
|
||||
{
|
||||
if(size() == m_capacity)
|
||||
{
|
||||
insert_overflow(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
insert(value);
|
||||
}
|
||||
}
|
||||
/// \brief Removes the top element of the stack.
|
||||
void pop()
|
||||
{
|
||||
Allocator::destroy(--m_end);
|
||||
}
|
||||
/// \brief Returns the top element of the mutable stack.
|
||||
Type& top()
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
/// \brief Returns the top element of the non-mutable stack.
|
||||
const Type& top() const
|
||||
{
|
||||
return *(m_end-1);
|
||||
}
|
||||
/// \brief Returns the element below the top element of the mutable stack.
|
||||
Type& parent()
|
||||
{
|
||||
return *(m_end-2);
|
||||
}
|
||||
/// \brief Returns the element below the top element of the non-mutable stack.
|
||||
const Type& parent() const
|
||||
{
|
||||
return *(m_end-2);
|
||||
}
|
||||
/// \brief Swaps the values of this stack and \p other.
|
||||
void swap(Stack& other)
|
||||
{
|
||||
std::swap(m_data, other.m_data);
|
||||
std::swap(m_end, other.m_end);
|
||||
std::swap(m_capacity, other.m_capacity);
|
||||
}
|
||||
#if 1 // use copy-swap technique
|
||||
Stack& operator=(const Stack& other)
|
||||
{
|
||||
Stack temp(other);
|
||||
temp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#else // avoids memory allocation if capacity is already sufficient.
|
||||
Stack& operator=(const Stack& other)
|
||||
{
|
||||
if(&other != this)
|
||||
{
|
||||
destroy();
|
||||
|
||||
if(other.size() > m_capacity)
|
||||
{
|
||||
Allocator::deallocate(m_data, m_capacity);
|
||||
m_capacity = other.m_capacity;
|
||||
m_data = Allocator::allocate(m_capacity);
|
||||
}
|
||||
m_end = m_data + other.size();
|
||||
|
||||
construct(other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \brief Returns true if \p self is lexicographically less than \p other.
|
||||
template<typename Type>
|
||||
inline bool operator<(const Stack<Type>& self, const Stack<Type>& other)
|
||||
{
|
||||
return std::lexicographical_compare(self.begin(), self.end(), other.begin(), other.end());
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap().
|
||||
template<typename Type>
|
||||
inline void swap(Stack<Type>& self, Stack<Type>& other)
|
||||
{
|
||||
self.swap(other);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue