/* 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_CONTAINER_H) #define INCLUDED_CONTAINER_CONTAINER_H #include #include #include "generic/static.h" /// \brief A single-value container, which can either be empty or full. template class Single { Type* m_value; public: Single() : m_value(0) { } bool empty() { return m_value == 0; } Type* insert(const Type& other) { m_value = new Type(other); return m_value; } void clear() { delete m_value; m_value = 0; } Type& get() { //ASSERT_MESSAGE(!empty(), "Single: must be initialised before being accessed"); return *m_value; } const Type& get() const { //ASSERT_MESSAGE(!empty(), "Single: must be initialised before being accessed"); return *m_value; } }; /// \brief An adaptor to make std::list into a Unique Sequence - which cannot contain the same value more than once. /// \param Value Uniquely identifies itself. Must provide a copy-constructor and an equality operator. template class UnsortedSet { typedef typename std::list Values; Values m_values; public: typedef typename Values::iterator iterator; typedef typename Values::const_iterator const_iterator; typedef typename Values::reverse_iterator reverse_iterator; typedef typename Values::const_reverse_iterator const_reverse_iterator; iterator begin() { return m_values.begin(); } const_iterator begin() const { return m_values.begin(); } iterator end() { return m_values.end(); } const_iterator end() const { return m_values.end(); } reverse_iterator rbegin() { return m_values.rbegin(); } const_reverse_iterator rbegin() const { return m_values.rbegin(); } reverse_iterator rend() { return m_values.rend(); } const_reverse_iterator rend() const { return m_values.rend(); } bool empty() const { return m_values.empty(); } std::size_t size() const { return m_values.size(); } void clear() { m_values.clear(); } void swap(UnsortedSet& other) { std::swap(m_values, other.m_values); } iterator insert(const Value& value) { ASSERT_MESSAGE(find(value) == end(), "UnsortedSet::insert: already added"); m_values.push_back(value); return --end(); } void erase(const Value& value) { iterator i = find(value); ASSERT_MESSAGE(i != end(), "UnsortedSet::erase: not found"); m_values.erase(i); } iterator find(const Value& value) { return std::find(begin(), end(), value); } }; namespace std { /// \brief Swaps the values of \p self and \p other. /// Overloads std::swap. template inline void swap(UnsortedSet& self, UnsortedSet& other) { self.swap(other); } } /// An adaptor to make std::list into a Unique Associative Sequence - which cannot contain the same value more than once. /// Key: Uniquely identifies a value. Must provide a copy-constructor and an equality operator. /// Value: Must provide a copy-constructor. template class UnsortedMap { typedef typename std::list< std::pair > Values; Values m_values; public: typedef typename Values::value_type value_type; typedef typename Values::iterator iterator; typedef typename Values::const_iterator const_iterator; iterator begin() { return m_values.begin(); } const_iterator begin() const { return m_values.begin(); } iterator end() { return m_values.end(); } const_iterator end() const { return m_values.end(); } bool empty() const { return m_values.empty(); } std::size_t size() const { return m_values.size(); } void clear() { m_values.clear(); } iterator insert(const value_type& value) { ASSERT_MESSAGE(find(value.first) == end(), "UnsortedMap::insert: already added"); m_values.push_back(value); return --m_values.end(); } void erase(const Key& key) { iterator i = find(key); ASSERT_MESSAGE(i != end(), "UnsortedMap::erase: not found"); erase(i); } void erase(iterator i) { m_values.erase(i); } iterator find(const Key& key) { for(iterator i = m_values.begin(); i != m_values.end(); ++i) { if((*i).first == key) { return i; } } return m_values.end(); } const_iterator find(const Key& key) const { for(const_iterator i = m_values.begin(); i != m_values.end(); ++i) { if((*i).first == key) { return i; } } return m_values.end(); } Value& operator[](const Key& key) { iterator i = find(key); if(i != end()) { return (*i).second; } m_values.push_back(Values::value_type(key, Value())); return m_values.back().second; } }; /// An adaptor to assert when duplicate values are added, or non-existent values removed from a std::set. template class UniqueSet { typedef std::set Values; Values m_values; public: typedef typename Values::iterator iterator; typedef typename Values::const_iterator const_iterator; typedef typename Values::reverse_iterator reverse_iterator; typedef typename Values::const_reverse_iterator const_reverse_iterator; iterator begin() { return m_values.begin(); } const_iterator begin() const { return m_values.begin(); } iterator end() { return m_values.end(); } const_iterator end() const { return m_values.end(); } reverse_iterator rbegin() { return m_values.rbegin(); } const_reverse_iterator rbegin() const { return m_values.rbegin(); } reverse_iterator rend() { return m_values.rend(); } const_reverse_iterator rend() const { return m_values.rend(); } bool empty() const { return m_values.empty(); } std::size_t size() const { return m_values.size(); } void clear() { m_values.clear(); } void swap(UniqueSet& other) { std::swap(m_values, other.m_values); } iterator insert(const Value& value) { std::pair result = m_values.insert(value); ASSERT_MESSAGE(result.second, "UniqueSet::insert: already added"); return result.first; } void erase(const Value& value) { iterator i = find(value); ASSERT_MESSAGE(i != end(), "UniqueSet::erase: not found"); m_values.erase(i); } iterator find(const Value& value) { return std::find(begin(), end(), value); } }; namespace std { /// \brief Swaps the values of \p self and \p other. /// Overloads std::swap. template inline void swap(UniqueSet& self, UniqueSet& other) { self.swap(other); } } template class ReferencePair { Type* m_first; Type* m_second; public: ReferencePair() : m_first(0), m_second(0) { } void attach(Type& t) { ASSERT_MESSAGE(m_first == 0 || m_second == 0, "ReferencePair::insert: pointer already exists"); if(m_first == 0) { m_first = &t; } else if(m_second == 0) { m_second = &t; } } void detach(Type& t) { ASSERT_MESSAGE(m_first == &t || m_second == &t, "ReferencePair::erase: pointer not found"); if(m_first == &t) { m_first = 0; } else if(m_second == &t) { m_second = 0; } } template void forEach(const Functor& functor) { if(m_second != 0) { functor(*m_second); } if(m_first != 0) { functor(*m_first); } } }; #endif