my own uncrustify run
This commit is contained in:
@@ -1,39 +1,37 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "array.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class Bleh
|
||||
{
|
||||
Array<int> m_array;
|
||||
public:
|
||||
Bleh() : m_array(16)
|
||||
{
|
||||
}
|
||||
};
|
||||
class Bleh
|
||||
{
|
||||
Array<int> m_array;
|
||||
public:
|
||||
Bleh() : m_array( 16 ){
|
||||
}
|
||||
};
|
||||
|
||||
void testAutoArray()
|
||||
{
|
||||
Array<Bleh> array(32);
|
||||
}
|
||||
void testAutoArray(){
|
||||
Array<Bleh> array( 32 );
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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_ARRAY_H)
|
||||
#if !defined( INCLUDED_CONTAINER_ARRAY_H )
|
||||
#define INCLUDED_CONTAINER_ARRAY_H
|
||||
|
||||
#include <cstddef>
|
||||
@@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
/// \brief An array whose size is variable at run-time.
|
||||
///
|
||||
/// - Resizing the array destroys all the existing elements and invalidates all iterators.
|
||||
/// - Default-Constructible, Copyable, Assignable.
|
||||
/// - Default-Constructible, Copyable, Assignable.
|
||||
/// - Compatible with the containers and algorithms in the Standard Template Library (STL) - http://www.sgi.com/tech/stl/
|
||||
///
|
||||
/// \param Element The type to be stored in the array. Must provide a default-constructor and a copy-constructor.
|
||||
@@ -38,160 +38,133 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
template<typename Element, typename Allocator = DefaultAllocator<Element> >
|
||||
class Array : public Allocator
|
||||
{
|
||||
std::size_t m_size;
|
||||
Element* m_data;
|
||||
std::size_t m_size;
|
||||
Element* m_data;
|
||||
|
||||
Element* construct(std::size_t size)
|
||||
{
|
||||
Element* construct( std::size_t size ){
|
||||
#if 1
|
||||
return New<Element, Allocator>(*this).vector(size);
|
||||
return New<Element, Allocator>( *this ).vector( size );
|
||||
#else
|
||||
return new Element[size];
|
||||
return new Element[size];
|
||||
#endif
|
||||
}
|
||||
template<typename T1>
|
||||
Element* construct(std::size_t size, const T1& value)
|
||||
{
|
||||
return New<Element, Allocator>(*this).vector(size, value);
|
||||
}
|
||||
void destroy(Element* data, std::size_t size)
|
||||
{
|
||||
}
|
||||
template<typename T1>
|
||||
Element* construct( std::size_t size, const T1& value ){
|
||||
return New<Element, Allocator>( *this ).vector( size, value );
|
||||
}
|
||||
void destroy( Element* data, std::size_t size ){
|
||||
#if 1
|
||||
Delete<Element, Allocator>(*this).vector(data, size);
|
||||
Delete<Element, Allocator>( *this ).vector( data, size );
|
||||
#else
|
||||
delete[] data;
|
||||
delete[] data;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Element value_type;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
typedef Element value_type;
|
||||
typedef value_type* iterator;
|
||||
typedef const value_type* const_iterator;
|
||||
|
||||
Array()
|
||||
: m_size(0), m_data(0)
|
||||
{
|
||||
}
|
||||
Array(std::size_t size)
|
||||
: m_size(size), m_data(construct(size))
|
||||
{
|
||||
}
|
||||
template<typename T1>
|
||||
Array(std::size_t size, const T1& value)
|
||||
: m_size(size), m_data(construct(size, value))
|
||||
{
|
||||
}
|
||||
Array(const Array& other)
|
||||
: Allocator(other), m_size(other.size()), m_data(construct(m_size))
|
||||
{
|
||||
std::copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
template<typename Iterator>
|
||||
Array(Iterator start, Iterator finish)
|
||||
: m_size(std::distance(start, finish)), m_data(construct(m_size))
|
||||
{
|
||||
std::copy(start, finish, begin());
|
||||
}
|
||||
~Array()
|
||||
{
|
||||
destroy(m_data, m_size);
|
||||
}
|
||||
Array()
|
||||
: m_size( 0 ), m_data( 0 ){
|
||||
}
|
||||
Array( std::size_t size )
|
||||
: m_size( size ), m_data( construct( size ) ){
|
||||
}
|
||||
template<typename T1>
|
||||
Array( std::size_t size, const T1& value )
|
||||
: m_size( size ), m_data( construct( size, value ) ){
|
||||
}
|
||||
Array( const Array& other )
|
||||
: Allocator( other ), m_size( other.size() ), m_data( construct( m_size ) ){
|
||||
std::copy( other.begin(), other.end(), begin() );
|
||||
}
|
||||
template<typename Iterator>
|
||||
Array( Iterator start, Iterator finish )
|
||||
: m_size( std::distance( start, finish ) ), m_data( construct( m_size ) ){
|
||||
std::copy( start, finish, begin() );
|
||||
}
|
||||
~Array(){
|
||||
destroy( m_data, m_size );
|
||||
}
|
||||
|
||||
Array& operator=(const Array& other)
|
||||
{
|
||||
if(other.size() == size())
|
||||
{
|
||||
std::copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
Array temp(other);
|
||||
temp.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Array& operator=( const Array& other ){
|
||||
if ( other.size() == size() ) {
|
||||
std::copy( other.begin(), other.end(), begin() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Array temp( other );
|
||||
temp.swap( *this );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(Array& other)
|
||||
{
|
||||
std::swap(m_size, other.m_size);
|
||||
std::swap(m_data, other.m_data);
|
||||
}
|
||||
void swap( Array& other ){
|
||||
std::swap( m_size, other.m_size );
|
||||
std::swap( m_data, other.m_data );
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
const_iterator begin() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return m_data + m_size;
|
||||
}
|
||||
const_iterator end() const
|
||||
{
|
||||
return m_data + m_size;
|
||||
}
|
||||
iterator begin(){
|
||||
return m_data;
|
||||
}
|
||||
const_iterator begin() const {
|
||||
return m_data;
|
||||
}
|
||||
iterator end(){
|
||||
return m_data + m_size;
|
||||
}
|
||||
const_iterator end() const {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
value_type& operator[](std::size_t index)
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
ASSERT_MESSAGE(index < size(), "array index out of bounds");
|
||||
value_type& operator[]( std::size_t index ){
|
||||
#if defined( _DEBUG )
|
||||
ASSERT_MESSAGE( index < size(), "array index out of bounds" );
|
||||
#endif
|
||||
return m_data[index];
|
||||
}
|
||||
const value_type& operator[](std::size_t index) const
|
||||
{
|
||||
#if defined(_DEBUG)
|
||||
ASSERT_MESSAGE(index < size(), "array index out of bounds");
|
||||
return m_data[index];
|
||||
}
|
||||
const value_type& operator[]( std::size_t index ) const {
|
||||
#if defined( _DEBUG )
|
||||
ASSERT_MESSAGE( index < size(), "array index out of bounds" );
|
||||
#endif
|
||||
return m_data[index];
|
||||
}
|
||||
value_type* data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
const value_type* data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
return m_data[index];
|
||||
}
|
||||
value_type* data(){
|
||||
return m_data;
|
||||
}
|
||||
const value_type* data() const {
|
||||
return m_data;
|
||||
}
|
||||
std::size_t size() const {
|
||||
return m_size;
|
||||
}
|
||||
bool empty() const {
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
void resize(std::size_t count)
|
||||
{
|
||||
if(count != size())
|
||||
{
|
||||
Array temp(count);
|
||||
temp.swap(*this);
|
||||
}
|
||||
}
|
||||
void resize(std::size_t count, const value_type& value)
|
||||
{
|
||||
if(count != size())
|
||||
{
|
||||
Array temp(count, value);
|
||||
temp.swap(*this);
|
||||
}
|
||||
}
|
||||
void resize( std::size_t count ){
|
||||
if ( count != size() ) {
|
||||
Array temp( count );
|
||||
temp.swap( *this );
|
||||
}
|
||||
}
|
||||
void resize( std::size_t count, const value_type& value ){
|
||||
if ( count != size() ) {
|
||||
Array temp( count, value );
|
||||
temp.swap( *this );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap.
|
||||
template<typename Element, typename Allocator>
|
||||
inline void swap(Array<Element, Allocator>& self, Array<Element, Allocator>& other)
|
||||
{
|
||||
self.swap(other);
|
||||
}
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap.
|
||||
template<typename Element, typename Allocator>
|
||||
inline void swap( Array<Element, Allocator>& self, Array<Element, Allocator>& other ){
|
||||
self.swap( other );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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_CACHE_H)
|
||||
#if !defined( INCLUDED_CONTAINER_CACHE_H )
|
||||
#define INCLUDED_CONTAINER_CACHE_H
|
||||
|
||||
#include <cstddef>
|
||||
@@ -30,69 +30,57 @@ template<typename Type, typename Parameter>
|
||||
class DefaultCreationPolicy
|
||||
{
|
||||
public:
|
||||
Type* construct(const Parameter& parameter)
|
||||
{
|
||||
return New<Type>().scalar(parameter);
|
||||
}
|
||||
void destroy(Type* p)
|
||||
{
|
||||
Delete<Type>().scalar(p);
|
||||
}
|
||||
Type* construct( const Parameter& parameter ){
|
||||
return New<Type>().scalar( parameter );
|
||||
}
|
||||
void destroy( Type* p ){
|
||||
Delete<Type>().scalar( p );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class SharedValue
|
||||
{
|
||||
typedef Type value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef Type value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
|
||||
std::size_t m_count;
|
||||
pointer m_value;
|
||||
std::size_t m_count;
|
||||
pointer m_value;
|
||||
|
||||
public:
|
||||
SharedValue()
|
||||
: m_count(0), m_value(0)
|
||||
{
|
||||
}
|
||||
~SharedValue()
|
||||
{
|
||||
ASSERT_MESSAGE(m_count == 0 , "destroying a referenced object\n");
|
||||
}
|
||||
void set(pointer value)
|
||||
{
|
||||
m_value = value;
|
||||
}
|
||||
pointer get()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
std::size_t increment()
|
||||
{
|
||||
return ++m_count;
|
||||
}
|
||||
std::size_t decrement()
|
||||
{
|
||||
ASSERT_MESSAGE(!empty(), "destroying a non-existent object\n");
|
||||
return --m_count;
|
||||
}
|
||||
std::size_t count()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
return m_count == 0;
|
||||
}
|
||||
reference operator*() const
|
||||
{
|
||||
ASSERT_NOTNULL(m_value);
|
||||
return *m_value;
|
||||
}
|
||||
pointer operator->() const
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
SharedValue()
|
||||
: m_count( 0 ), m_value( 0 ){
|
||||
}
|
||||
~SharedValue(){
|
||||
ASSERT_MESSAGE( m_count == 0, "destroying a referenced object\n" );
|
||||
}
|
||||
void set( pointer value ){
|
||||
m_value = value;
|
||||
}
|
||||
pointer get(){
|
||||
return m_value;
|
||||
}
|
||||
std::size_t increment(){
|
||||
return ++m_count;
|
||||
}
|
||||
std::size_t decrement(){
|
||||
ASSERT_MESSAGE( !empty(), "destroying a non-existent object\n" );
|
||||
return --m_count;
|
||||
}
|
||||
std::size_t count(){
|
||||
return m_count;
|
||||
}
|
||||
bool empty(){
|
||||
return m_count == 0;
|
||||
}
|
||||
reference operator*() const {
|
||||
ASSERT_NOTNULL( m_value );
|
||||
return *m_value;
|
||||
}
|
||||
pointer operator->() const {
|
||||
return &( operator*() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -107,99 +95,83 @@ public:
|
||||
template<typename Key, typename Cached, typename Hasher, typename KeyEqual = std::equal_to<Key>, typename CreationPolicy = DefaultCreationPolicy<Cached, Key> >
|
||||
class HashedCache : public CreationPolicy
|
||||
{
|
||||
typedef SharedValue<Cached> Element;
|
||||
typedef HashTable<Key, Element, Hasher, KeyEqual> map_type;
|
||||
typedef SharedValue<Cached> Element;
|
||||
typedef HashTable<Key, Element, Hasher, KeyEqual> map_type;
|
||||
|
||||
map_type m_map;
|
||||
map_type m_map;
|
||||
|
||||
public:
|
||||
explicit HashedCache(const CreationPolicy& creation = CreationPolicy())
|
||||
: CreationPolicy(creation), m_map(256)
|
||||
{
|
||||
}
|
||||
~HashedCache()
|
||||
{
|
||||
ASSERT_MESSAGE(empty(), "HashedCache::~HashedCache: not empty");
|
||||
}
|
||||
explicit HashedCache( const CreationPolicy& creation = CreationPolicy() )
|
||||
: CreationPolicy( creation ), m_map( 256 ){
|
||||
}
|
||||
~HashedCache(){
|
||||
ASSERT_MESSAGE( empty(), "HashedCache::~HashedCache: not empty" );
|
||||
}
|
||||
|
||||
typedef typename map_type::iterator iterator;
|
||||
typedef typename map_type::value_type value_type;
|
||||
typedef typename map_type::iterator iterator;
|
||||
typedef typename map_type::value_type value_type;
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return m_map.begin();
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return m_map.end();
|
||||
}
|
||||
iterator begin(){
|
||||
return m_map.begin();
|
||||
}
|
||||
iterator end(){
|
||||
return m_map.end();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_map.empty();
|
||||
}
|
||||
bool empty() const {
|
||||
return m_map.empty();
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
{
|
||||
return m_map.find(key);
|
||||
}
|
||||
iterator find( const Key& key ){
|
||||
return m_map.find( key );
|
||||
}
|
||||
|
||||
void capture(iterator i)
|
||||
{
|
||||
(*i).value.increment();
|
||||
}
|
||||
void release(iterator i)
|
||||
{
|
||||
if((*i).value.decrement() == 0)
|
||||
{
|
||||
CreationPolicy::destroy((*i).value.get());
|
||||
m_map.erase(i);
|
||||
}
|
||||
}
|
||||
void capture( iterator i ){
|
||||
( *i ).value.increment();
|
||||
}
|
||||
void release( iterator i ){
|
||||
if ( ( *i ).value.decrement() == 0 ) {
|
||||
CreationPolicy::destroy( ( *i ).value.get() );
|
||||
m_map.erase( i );
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
Element& capture(const Key& key)
|
||||
{
|
||||
Element& capture( const Key& key ){
|
||||
#if 0
|
||||
Element& elem = m_map[key];
|
||||
if(elem.increment() == 1)
|
||||
{
|
||||
elem.set(CreationPolicy::construct(key));
|
||||
}
|
||||
return elem;
|
||||
Element& elem = m_map[key];
|
||||
if ( elem.increment() == 1 ) {
|
||||
elem.set( CreationPolicy::construct( key ) );
|
||||
}
|
||||
return elem;
|
||||
#else
|
||||
iterator i = m_map.insert(key, Element());
|
||||
if((*i).value.increment() == 1)
|
||||
{
|
||||
(*i).value.set(CreationPolicy::construct((*i).key));
|
||||
}
|
||||
return (*i).value;
|
||||
iterator i = m_map.insert( key, Element() );
|
||||
if ( ( *i ).value.increment() == 1 ) {
|
||||
( *i ).value.set( CreationPolicy::construct( ( *i ).key ) );
|
||||
}
|
||||
return ( *i ).value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
value_type& capture(const Key& key)
|
||||
{
|
||||
iterator i = m_map.find(key);
|
||||
if(i == m_map.end())
|
||||
{
|
||||
i = m_map.insert(key, Element());
|
||||
(*i).value.set(CreationPolicy::construct((*i).key));
|
||||
}
|
||||
(*i).value.increment();
|
||||
return (*i);
|
||||
}
|
||||
value_type& capture( const Key& key ){
|
||||
iterator i = m_map.find( key );
|
||||
if ( i == m_map.end() ) {
|
||||
i = m_map.insert( key, Element() );
|
||||
( *i ).value.set( CreationPolicy::construct( ( *i ).key ) );
|
||||
}
|
||||
( *i ).value.increment();
|
||||
return ( *i );
|
||||
}
|
||||
#endif
|
||||
void release(const Key& key)
|
||||
{
|
||||
iterator i = m_map.find(key);
|
||||
ASSERT_MESSAGE(i != m_map.end(), "releasing a non-existent object\n");
|
||||
release(i);
|
||||
}
|
||||
void release( const Key& key ){
|
||||
iterator i = m_map.find( key );
|
||||
ASSERT_MESSAGE( i != m_map.end(), "releasing a non-existent object\n" );
|
||||
release( i );
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_map.clear();
|
||||
}
|
||||
void clear(){
|
||||
m_map.clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "container.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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)
|
||||
#if !defined( INCLUDED_CONTAINER_CONTAINER_H )
|
||||
#define INCLUDED_CONTAINER_CONTAINER_H
|
||||
|
||||
#include <list>
|
||||
@@ -31,35 +31,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
template<typename Type>
|
||||
class Single
|
||||
{
|
||||
Type* m_value;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -68,91 +62,75 @@ public:
|
||||
template<typename Value>
|
||||
class UnsortedSet
|
||||
{
|
||||
typedef typename std::list<Value> Values;
|
||||
Values m_values;
|
||||
typedef typename std::list<Value> 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;
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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);
|
||||
}
|
||||
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<typename Value>
|
||||
inline void swap(UnsortedSet<Value>& self, UnsortedSet<Value>& other)
|
||||
{
|
||||
self.swap(other);
|
||||
}
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap.
|
||||
template<typename Value>
|
||||
inline void swap( UnsortedSet<Value>& self, UnsortedSet<Value>& other ){
|
||||
self.swap( other );
|
||||
}
|
||||
}
|
||||
|
||||
/// An adaptor to make std::list into a Unique Associative Sequence - which cannot contain the same value more than once.
|
||||
@@ -161,232 +139,190 @@ namespace std
|
||||
template<typename Key, typename Value>
|
||||
class UnsortedMap
|
||||
{
|
||||
typedef typename std::list< std::pair<Key, Value> > Values;
|
||||
Values m_values;
|
||||
typedef typename std::list< std::pair<Key, Value> > Values;
|
||||
Values m_values;
|
||||
public:
|
||||
typedef typename Values::value_type value_type;
|
||||
typedef typename Values::iterator iterator;
|
||||
typedef typename Values::const_iterator const_iterator;
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
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<typename Value>
|
||||
class UniqueSet
|
||||
{
|
||||
typedef std::set<Value> Values;
|
||||
Values m_values;
|
||||
typedef std::set<Value> 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;
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
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<iterator, bool> 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);
|
||||
}
|
||||
void swap( UniqueSet& other ){
|
||||
std::swap( m_values, other.m_values );
|
||||
}
|
||||
iterator insert( const Value& value ){
|
||||
std::pair<iterator, bool> 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<typename Value>
|
||||
inline void swap(UniqueSet<Value>& self, UniqueSet<Value>& other)
|
||||
{
|
||||
self.swap(other);
|
||||
}
|
||||
/// \brief Swaps the values of \p self and \p other.
|
||||
/// Overloads std::swap.
|
||||
template<typename Value>
|
||||
inline void swap( UniqueSet<Value>& self, UniqueSet<Value>& other ){
|
||||
self.swap( other );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
class ReferencePair
|
||||
{
|
||||
Type* m_first;
|
||||
Type* m_second;
|
||||
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<typename Functor>
|
||||
void forEach(const Functor& functor)
|
||||
{
|
||||
if(m_second != 0)
|
||||
{
|
||||
functor(*m_second);
|
||||
}
|
||||
if(m_first != 0)
|
||||
{
|
||||
functor(*m_first);
|
||||
}
|
||||
}
|
||||
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<typename Functor>
|
||||
void forEach( const Functor& functor ){
|
||||
if ( m_second != 0 ) {
|
||||
functor( *m_second );
|
||||
}
|
||||
if ( m_first != 0 ) {
|
||||
functor( *m_first );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "hashfunc.h"
|
||||
|
||||
@@ -1,359 +1,338 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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_HASHFUNC_H)
|
||||
#if !defined( INCLUDED_CONTAINER_HASHFUNC_H )
|
||||
#define INCLUDED_CONTAINER_HASHFUNC_H
|
||||
|
||||
#include <cctype>
|
||||
#include "string/string.h"
|
||||
#include "container/array.h"
|
||||
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
||||
typedef unsigned char ub1;
|
||||
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
|
||||
typedef unsigned char ub1;
|
||||
|
||||
inline ub1 ub1_as_ub1_nocase(ub1 byte)
|
||||
{
|
||||
return std::tolower(byte);
|
||||
inline ub1 ub1_as_ub1_nocase( ub1 byte ){
|
||||
return std::tolower( byte );
|
||||
}
|
||||
|
||||
inline ub4 ub1x4_as_ub4_nocase(const ub1 bytes[4])
|
||||
{
|
||||
ub4 result;
|
||||
reinterpret_cast<ub1*>(&result)[0] = ub1_as_ub1_nocase(bytes[0]);
|
||||
reinterpret_cast<ub1*>(&result)[1] = ub1_as_ub1_nocase(bytes[1]);
|
||||
reinterpret_cast<ub1*>(&result)[2] = ub1_as_ub1_nocase(bytes[2]);
|
||||
reinterpret_cast<ub1*>(&result)[3] = ub1_as_ub1_nocase(bytes[3]);
|
||||
return result;
|
||||
inline ub4 ub1x4_as_ub4_nocase( const ub1 bytes[4] ){
|
||||
ub4 result;
|
||||
reinterpret_cast<ub1*>( &result )[0] = ub1_as_ub1_nocase( bytes[0] );
|
||||
reinterpret_cast<ub1*>( &result )[1] = ub1_as_ub1_nocase( bytes[1] );
|
||||
reinterpret_cast<ub1*>( &result )[2] = ub1_as_ub1_nocase( bytes[2] );
|
||||
reinterpret_cast<ub1*>( &result )[3] = ub1_as_ub1_nocase( bytes[3] );
|
||||
return result;
|
||||
}
|
||||
|
||||
class ub1_default_traits
|
||||
{
|
||||
public:
|
||||
static ub1 as_ub1(ub1 byte)
|
||||
{
|
||||
return byte;
|
||||
}
|
||||
static ub1 as_ub1( ub1 byte ){
|
||||
return byte;
|
||||
}
|
||||
};
|
||||
|
||||
class ub1_nocase_traits
|
||||
{
|
||||
public:
|
||||
static ub1 as_ub1(ub1 byte)
|
||||
{
|
||||
return ub1_as_ub1_nocase(byte);
|
||||
}
|
||||
static ub1 as_ub1( ub1 byte ){
|
||||
return ub1_as_ub1_nocase( byte );
|
||||
}
|
||||
};
|
||||
|
||||
class ub1x4_default_traits
|
||||
{
|
||||
public:
|
||||
static ub4 as_ub4(const ub1 bytes[4])
|
||||
{
|
||||
return *reinterpret_cast<const ub4*>(bytes);
|
||||
}
|
||||
static ub4 as_ub4( const ub1 bytes[4] ){
|
||||
return *reinterpret_cast<const ub4*>( bytes );
|
||||
}
|
||||
};
|
||||
|
||||
class ub1x4_nocase_traits
|
||||
{
|
||||
public:
|
||||
static ub4 as_ub4(const ub1 bytes[4])
|
||||
{
|
||||
return ub1x4_as_ub4_nocase(bytes);
|
||||
}
|
||||
static ub4 as_ub4( const ub1 bytes[4] ){
|
||||
return ub1x4_as_ub4_nocase( bytes );
|
||||
}
|
||||
};
|
||||
|
||||
class ub4_default_traits
|
||||
{
|
||||
public:
|
||||
static ub4 as_ub4(ub4 i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
static ub4 as_ub4( ub4 i ){
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
class ub4_nocase_traits
|
||||
{
|
||||
public:
|
||||
static ub4 as_ub4(ub4 i)
|
||||
{
|
||||
return ub1x4_as_ub4_nocase(reinterpret_cast<const ub1*>(&i));
|
||||
}
|
||||
static ub4 as_ub4( ub4 i ){
|
||||
return ub1x4_as_ub4_nocase( reinterpret_cast<const ub1*>( &i ) );
|
||||
}
|
||||
};
|
||||
|
||||
// lookup2.c
|
||||
// By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
|
||||
// code any way you wish, private, educational, or commercial. It's free.
|
||||
|
||||
#define hashsize(n) ((ub4)1<<(n))
|
||||
#define hashmask(n) (hashsize(n)-1)
|
||||
#define hashsize( n ) ( (ub4)1 << ( n ) )
|
||||
#define hashmask( n ) ( hashsize( n ) - 1 )
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
For every delta with one or two bit set, and the deltas of all three
|
||||
high bits or all three low bits, whether the original value of a,b,c
|
||||
is almost all zero or is uniformly distributed,
|
||||
* If mix() is run forward or backward, at least 32 bits in a,b,c
|
||||
have at least 1/4 probability of changing.
|
||||
* If mix() is run forward, every bit of c will change between 1/3 and
|
||||
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
|
||||
mix() was built out of 36 single-cycle latency instructions in a
|
||||
structure that could supported 2x parallelism, like so:
|
||||
a -= b;
|
||||
--------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
For every delta with one or two bit set, and the deltas of all three
|
||||
high bits or all three low bits, whether the original value of a,b,c
|
||||
is almost all zero or is uniformly distributed,
|
||||
* If mix() is run forward or backward, at least 32 bits in a,b,c
|
||||
have at least 1/4 probability of changing.
|
||||
* If mix() is run forward, every bit of c will change between 1/3 and
|
||||
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
|
||||
mix() was built out of 36 single-cycle latency instructions in a
|
||||
structure that could supported 2x parallelism, like so:
|
||||
a -= b;
|
||||
a -= c; x = (c>>13);
|
||||
b -= c; a ^= x;
|
||||
b -= a; x = (a<<8);
|
||||
c -= a; b ^= x;
|
||||
c -= b; x = (b>>13);
|
||||
...
|
||||
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
|
||||
of that parallelism. They've also turned some of those single-cycle
|
||||
latency instructions into multi-cycle latency instructions. Still,
|
||||
this is the fastest good hash I could find. There were about 2^^68
|
||||
to choose from. I only looked at a billion or so.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
#define mix(a,b,c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
b -= c; b -= a; b ^= (a<<8); \
|
||||
c -= a; c -= b; c ^= (b>>13); \
|
||||
a -= b; a -= c; a ^= (c>>12); \
|
||||
b -= c; b -= a; b ^= (a<<16); \
|
||||
c -= a; c -= b; c ^= (b>>5); \
|
||||
a -= b; a -= c; a ^= (c>>3); \
|
||||
b -= c; b -= a; b ^= (a<<10); \
|
||||
c -= a; c -= b; c ^= (b>>15); \
|
||||
}
|
||||
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
|
||||
of that parallelism. They've also turned some of those single-cycle
|
||||
latency instructions into multi-cycle latency instructions. Still,
|
||||
this is the fastest good hash I could find. There were about 2^^68
|
||||
to choose from. I only looked at a billion or so.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
#define mix( a,b,c ) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
}
|
||||
|
||||
/* same, but slower, works on systems that might have 8 byte ub4's */
|
||||
#define mix2(a,b,c) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= (c>>13); \
|
||||
b -= c; b -= a; b ^= (a<< 8); \
|
||||
c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
|
||||
a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
|
||||
b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
|
||||
c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
|
||||
a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
|
||||
b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
|
||||
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
|
||||
}
|
||||
#define mix2( a,b,c ) \
|
||||
{ \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( ( b & 0xffffffff ) >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( ( c & 0xffffffff ) >> 12 ); \
|
||||
b -= c; b -= a; b = ( b ^ ( a << 16 ) ) & 0xffffffff; \
|
||||
c -= a; c -= b; c = ( c ^ ( b >> 5 ) ) & 0xffffffff; \
|
||||
a -= b; a -= c; a = ( a ^ ( c >> 3 ) ) & 0xffffffff; \
|
||||
b -= c; b -= a; b = ( b ^ ( a << 10 ) ) & 0xffffffff; \
|
||||
c -= a; c -= b; c = ( c ^ ( b >> 15 ) ) & 0xffffffff; \
|
||||
}
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
hash() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
len : the length of the key, counting by bytes
|
||||
level : can be any 4-byte value
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Every 1-bit and 2-bit delta achieves avalanche.
|
||||
About 36+6len instructions.
|
||||
--------------------------------------------------------------------
|
||||
hash() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
len : the length of the key, counting by bytes
|
||||
level : can be any 4-byte value
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Every 1-bit and 2-bit delta achieves avalanche.
|
||||
About 36+6len instructions.
|
||||
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
|
||||
If you are hashing n strings (ub1 **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
|
||||
If you are hashing n strings (ub1 **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
|
||||
|
||||
See http://burlteburtle.net/bob/hash/evahash.html
|
||||
Use for hash table lookup, or anything where one collision in 2^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
See http://burlteburtle.net/bob/hash/evahash.html
|
||||
Use for hash table lookup, or anything where one collision in 2^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
template<typename UB1Traits, typename UB4x1Traits>
|
||||
inline ub4 hash(
|
||||
const ub1 *k, /* the key */
|
||||
ub4 length, /* the length of the key */
|
||||
ub4 initval, /* the previous hash, or an arbitrary value */
|
||||
const UB1Traits& ub1traits,
|
||||
const UB4x1Traits& ub4x1traits
|
||||
)
|
||||
{
|
||||
register ub4 a,b,c,len;
|
||||
const ub1 *k, /* the key */
|
||||
ub4 length, /* the length of the key */
|
||||
ub4 initval, /* the previous hash, or an arbitrary value */
|
||||
const UB1Traits& ub1traits,
|
||||
const UB4x1Traits& ub4x1traits
|
||||
){
|
||||
register ub4 a,b,c,len;
|
||||
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while (len >= 12)
|
||||
{
|
||||
a += (k[0] +((ub4)UB1Traits::as_ub1(k[1])<<8) +((ub4)UB1Traits::as_ub1(k[2])<<16) +((ub4)UB1Traits::as_ub1(k[3])<<24));
|
||||
b += (k[4] +((ub4)UB1Traits::as_ub1(k[5])<<8) +((ub4)UB1Traits::as_ub1(k[6])<<16) +((ub4)UB1Traits::as_ub1(k[7])<<24));
|
||||
c += (k[8] +((ub4)UB1Traits::as_ub1(k[9])<<8) +((ub4)UB1Traits::as_ub1(k[10])<<16)+((ub4)UB1Traits::as_ub1(k[11])<<24));
|
||||
mix(a,b,c);
|
||||
k += 12; len -= 12;
|
||||
}
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while ( len >= 12 )
|
||||
{
|
||||
a += ( k[0] + ( ( ub4 ) UB1Traits::as_ub1( k[1] ) << 8 ) + ( ( ub4 ) UB1Traits::as_ub1( k[2] ) << 16 ) + ( ( ub4 ) UB1Traits::as_ub1( k[3] ) << 24 ) );
|
||||
b += ( k[4] + ( ( ub4 ) UB1Traits::as_ub1( k[5] ) << 8 ) + ( ( ub4 ) UB1Traits::as_ub1( k[6] ) << 16 ) + ( ( ub4 ) UB1Traits::as_ub1( k[7] ) << 24 ) );
|
||||
c += ( k[8] + ( ( ub4 ) UB1Traits::as_ub1( k[9] ) << 8 ) + ( ( ub4 ) UB1Traits::as_ub1( k[10] ) << 16 ) + ( ( ub4 ) UB1Traits::as_ub1( k[11] ) << 24 ) );
|
||||
mix( a,b,c );
|
||||
k += 12; len -= 12;
|
||||
}
|
||||
|
||||
/*------------------------------------- handle the last 11 bytes */
|
||||
c += length;
|
||||
switch(len) /* all the case statements fall through */
|
||||
{
|
||||
case 11: c += ((ub4)UB1Traits::as_ub1(k[10]) << 24);
|
||||
case 10: c += ((ub4)UB1Traits::as_ub1(k[9]) << 16);
|
||||
case 9 : c += ((ub4)UB1Traits::as_ub1(k[8]) << 8);
|
||||
/* the first byte of c is reserved for the length */
|
||||
case 8 : b += ((ub4)UB1Traits::as_ub1(k[7]) << 24);
|
||||
case 7 : b += ((ub4)UB1Traits::as_ub1(k[6]) << 16);
|
||||
case 6 : b += ((ub4)UB1Traits::as_ub1(k[5]) << 8);
|
||||
case 5 : b += UB1Traits::as_ub1(k[4]);
|
||||
case 4 : a += ((ub4)UB1Traits::as_ub1(k[3]) << 24);
|
||||
case 3 : a += ((ub4)UB1Traits::as_ub1(k[2]) << 16);
|
||||
case 2 : a += ((ub4)UB1Traits::as_ub1(k[1]) << 8);
|
||||
case 1 : a += UB1Traits::as_ub1(k[0]);
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix(a,b,c);
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
/*------------------------------------- handle the last 11 bytes */
|
||||
c += length;
|
||||
switch ( len ) /* all the case statements fall through */
|
||||
{
|
||||
case 11: c += ( ( ub4 ) UB1Traits::as_ub1( k[10] ) << 24 );
|
||||
case 10: c += ( ( ub4 ) UB1Traits::as_ub1( k[9] ) << 16 );
|
||||
case 9: c += ( ( ub4 ) UB1Traits::as_ub1( k[8] ) << 8 );
|
||||
/* the first byte of c is reserved for the length */
|
||||
case 8: b += ( ( ub4 ) UB1Traits::as_ub1( k[7] ) << 24 );
|
||||
case 7: b += ( ( ub4 ) UB1Traits::as_ub1( k[6] ) << 16 );
|
||||
case 6: b += ( ( ub4 ) UB1Traits::as_ub1( k[5] ) << 8 );
|
||||
case 5: b += UB1Traits::as_ub1( k[4] );
|
||||
case 4: a += ( ( ub4 ) UB1Traits::as_ub1( k[3] ) << 24 );
|
||||
case 3: a += ( ( ub4 ) UB1Traits::as_ub1( k[2] ) << 16 );
|
||||
case 2: a += ( ( ub4 ) UB1Traits::as_ub1( k[1] ) << 8 );
|
||||
case 1: a += UB1Traits::as_ub1( k[0] );
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix( a,b,c );
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------
|
||||
This works on all machines. hash2() is identical to hash() on
|
||||
little-endian machines, except that the length has to be measured
|
||||
in ub4s instead of bytes. It is much faster than hash(). It
|
||||
requires
|
||||
-- that the key be an array of ub4's, and
|
||||
-- that all your machines have the same endianness, and
|
||||
-- that the length be the number of ub4's in the key
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
--------------------------------------------------------------------
|
||||
This works on all machines. hash2() is identical to hash() on
|
||||
little-endian machines, except that the length has to be measured
|
||||
in ub4s instead of bytes. It is much faster than hash(). It
|
||||
requires
|
||||
-- that the key be an array of ub4's, and
|
||||
-- that all your machines have the same endianness, and
|
||||
-- that the length be the number of ub4's in the key
|
||||
--------------------------------------------------------------------
|
||||
*/
|
||||
template<typename UB4Traits>
|
||||
inline ub4 hash2(
|
||||
const ub4 *k, /* the key */
|
||||
ub4 length, /* the length of the key, in ub4s */
|
||||
ub4 initval, /* the previous hash, or an arbitrary value */
|
||||
const UB4Traits& ub4traits
|
||||
)
|
||||
{
|
||||
register ub4 a,b,c,len;
|
||||
const ub4 *k, /* the key */
|
||||
ub4 length, /* the length of the key, in ub4s */
|
||||
ub4 initval, /* the previous hash, or an arbitrary value */
|
||||
const UB4Traits& ub4traits
|
||||
){
|
||||
register ub4 a,b,c,len;
|
||||
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
/* Set up the internal state */
|
||||
len = length;
|
||||
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
|
||||
c = initval; /* the previous hash value */
|
||||
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while (len >= 3)
|
||||
{
|
||||
a += UB4Traits::as_ub4(k[0]);
|
||||
b += UB4Traits::as_ub4(k[1]);
|
||||
c += UB4Traits::as_ub4(k[2]);
|
||||
mix(a,b,c);
|
||||
k += 3; len -= 3;
|
||||
}
|
||||
/*---------------------------------------- handle most of the key */
|
||||
while ( len >= 3 )
|
||||
{
|
||||
a += UB4Traits::as_ub4( k[0] );
|
||||
b += UB4Traits::as_ub4( k[1] );
|
||||
c += UB4Traits::as_ub4( k[2] );
|
||||
mix( a,b,c );
|
||||
k += 3; len -= 3;
|
||||
}
|
||||
|
||||
/*-------------------------------------- handle the last 2 ub4's */
|
||||
c += length;
|
||||
switch(len) /* all the case statements fall through */
|
||||
{
|
||||
/* c is reserved for the length */
|
||||
case 2 : b += UB4Traits::as_ub4(k[1]);
|
||||
case 1 : a += UB4Traits::as_ub4(k[0]);
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix(a,b,c);
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
/*-------------------------------------- handle the last 2 ub4's */
|
||||
c += length;
|
||||
switch ( len ) /* all the case statements fall through */
|
||||
{
|
||||
/* c is reserved for the length */
|
||||
case 2: b += UB4Traits::as_ub4( k[1] );
|
||||
case 1: a += UB4Traits::as_ub4( k[0] );
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
mix( a,b,c );
|
||||
/*-------------------------------------------- report the result */
|
||||
return c;
|
||||
}
|
||||
|
||||
typedef ub4 hash_t;
|
||||
|
||||
inline hash_t hash_ub1(const ub1* key, std::size_t len, hash_t previous = 0)
|
||||
{
|
||||
return hash(key, ub4(len), previous, ub1_default_traits(), ub1x4_default_traits());
|
||||
inline hash_t hash_ub1( const ub1* key, std::size_t len, hash_t previous = 0 ){
|
||||
return hash( key, ub4( len ), previous, ub1_default_traits(), ub1x4_default_traits() );
|
||||
}
|
||||
|
||||
inline hash_t hash_ub1_nocase(const ub1* key, std::size_t len, hash_t previous = 0)
|
||||
{
|
||||
return hash(key, ub4(len), previous, ub1_nocase_traits(), ub1x4_nocase_traits());
|
||||
inline hash_t hash_ub1_nocase( const ub1* key, std::size_t len, hash_t previous = 0 ){
|
||||
return hash( key, ub4( len ), previous, ub1_nocase_traits(), ub1x4_nocase_traits() );
|
||||
}
|
||||
|
||||
template<typename UB4Traits>
|
||||
inline hash_t hash_ub4(const ub4* key, std::size_t len, const UB4Traits& traits, hash_t previous = 0)
|
||||
{
|
||||
return hash2(key,ub4(len), previous, traits);
|
||||
inline hash_t hash_ub4( const ub4* key, std::size_t len, const UB4Traits& traits, hash_t previous = 0 ){
|
||||
return hash2( key,ub4( len ), previous, traits );
|
||||
}
|
||||
|
||||
inline ub4 hash_combine(ub4 left, ub4 right)
|
||||
{
|
||||
return hash_ub1(reinterpret_cast<const ub1*>(&left), 4, right);
|
||||
inline ub4 hash_combine( ub4 left, ub4 right ){
|
||||
return hash_ub1( reinterpret_cast<const ub1*>( &left ), 4, right );
|
||||
}
|
||||
|
||||
template<typename POD>
|
||||
inline hash_t pod_hash(const POD& pod)
|
||||
{
|
||||
return hash_ub1(reinterpret_cast<const ub1*>(&pod), sizeof(POD));
|
||||
inline hash_t pod_hash( const POD& pod ){
|
||||
return hash_ub1( reinterpret_cast<const ub1*>( &pod ), sizeof( POD ) );
|
||||
}
|
||||
|
||||
inline hash_t string_hash(const char* string, hash_t previous = 0)
|
||||
{
|
||||
return hash_ub1(reinterpret_cast<const ub1*>(string), string_length(string), previous);
|
||||
inline hash_t string_hash( const char* string, hash_t previous = 0 ){
|
||||
return hash_ub1( reinterpret_cast<const ub1*>( string ), string_length( string ), previous );
|
||||
}
|
||||
|
||||
inline hash_t string_hash_nocase(const char* string, hash_t previous = 0)
|
||||
{
|
||||
return hash_ub1_nocase(reinterpret_cast<const ub1*>(string), string_length(string), previous);
|
||||
inline hash_t string_hash_nocase( const char* string, hash_t previous = 0 ){
|
||||
return hash_ub1_nocase( reinterpret_cast<const ub1*>( string ), string_length( string ), previous );
|
||||
}
|
||||
|
||||
struct RawStringHash
|
||||
{
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()(const char* string) const
|
||||
{
|
||||
return string_hash(string);
|
||||
}
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()( const char* string ) const {
|
||||
return string_hash( string );
|
||||
}
|
||||
};
|
||||
|
||||
struct HashString
|
||||
{
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()(const CopiedString& string) const
|
||||
{
|
||||
return string_hash(string.c_str());
|
||||
}
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()( const CopiedString& string ) const {
|
||||
return string_hash( string.c_str() );
|
||||
}
|
||||
};
|
||||
|
||||
struct HashStringNoCase
|
||||
{
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()(const CopiedString& string) const
|
||||
{
|
||||
return string_hash_nocase(string.c_str());
|
||||
}
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()( const CopiedString& string ) const {
|
||||
return string_hash_nocase( string.c_str() );
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Length of a string in ub4.
|
||||
/// "wibble" (6) gives 2,
|
||||
/// "and" (3) gives 1,
|
||||
/// "bleh" (4) gives 2
|
||||
inline std::size_t string_length_ub4(const char* string)
|
||||
{
|
||||
return ((string_length(string)>>2)+1)<<2;
|
||||
inline std::size_t string_length_ub4( const char* string ){
|
||||
return ( ( string_length( string ) >> 2 ) + 1 ) << 2;
|
||||
}
|
||||
|
||||
/// \brief Hashable key type that stores a string as an array of ub4 - making hashing faster.
|
||||
@@ -361,72 +340,61 @@ inline std::size_t string_length_ub4(const char* string)
|
||||
template<typename UB4Traits = ub4_default_traits>
|
||||
class HashKey
|
||||
{
|
||||
Array<ub4> m_key;
|
||||
hash_t m_hash;
|
||||
Array<ub4> m_key;
|
||||
hash_t m_hash;
|
||||
|
||||
void copy(const HashKey& other)
|
||||
{
|
||||
std::copy(other.m_key.begin(), other.m_key.end(), m_key.begin());
|
||||
m_hash = other.m_hash;
|
||||
}
|
||||
void copy(const char* string)
|
||||
{
|
||||
strncpy(reinterpret_cast<char*>(m_key.data()), string, m_key.size());
|
||||
for(Array<ub4>::iterator i = m_key.begin(); i != m_key.end(); ++i)
|
||||
{
|
||||
*i = UB4Traits::as_ub4(*i);
|
||||
}
|
||||
m_hash = hash_ub4(m_key.data(), m_key.size(), ub4_default_traits());
|
||||
}
|
||||
bool equal(const HashKey& other) const
|
||||
{
|
||||
return m_hash == other.m_hash && m_key.size() == other.m_key.size()
|
||||
&& std::equal(m_key.begin(), m_key.end(), other.m_key.begin());
|
||||
}
|
||||
void copy( const HashKey& other ){
|
||||
std::copy( other.m_key.begin(), other.m_key.end(), m_key.begin() );
|
||||
m_hash = other.m_hash;
|
||||
}
|
||||
void copy( const char* string ){
|
||||
strncpy( reinterpret_cast<char*>( m_key.data() ), string, m_key.size() );
|
||||
for ( Array<ub4>::iterator i = m_key.begin(); i != m_key.end(); ++i )
|
||||
{
|
||||
*i = UB4Traits::as_ub4( *i );
|
||||
}
|
||||
m_hash = hash_ub4( m_key.data(), m_key.size(), ub4_default_traits() );
|
||||
}
|
||||
bool equal( const HashKey& other ) const {
|
||||
return m_hash == other.m_hash && m_key.size() == other.m_key.size()
|
||||
&& std::equal( m_key.begin(), m_key.end(), other.m_key.begin() );
|
||||
}
|
||||
|
||||
public:
|
||||
HashKey(const HashKey& other) : m_key(other.m_key.size())
|
||||
{
|
||||
copy(other);
|
||||
}
|
||||
HashKey(const char* string) : m_key(string_length_ub4(string))
|
||||
{
|
||||
copy(string);
|
||||
}
|
||||
HashKey& operator=(const char* string)
|
||||
{
|
||||
m_key.resize(string_length_ub4(string));
|
||||
copy(string);
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const HashKey& other) const
|
||||
{
|
||||
return equal(other);
|
||||
}
|
||||
bool operator!=(const HashKey& other) const
|
||||
{
|
||||
return !equal(other);
|
||||
}
|
||||
hash_t hash() const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
HashKey( const HashKey& other ) : m_key( other.m_key.size() ){
|
||||
copy( other );
|
||||
}
|
||||
HashKey( const char* string ) : m_key( string_length_ub4( string ) ){
|
||||
copy( string );
|
||||
}
|
||||
HashKey& operator=( const char* string ){
|
||||
m_key.resize( string_length_ub4( string ) );
|
||||
copy( string );
|
||||
return *this;
|
||||
}
|
||||
bool operator==( const HashKey& other ) const {
|
||||
return equal( other );
|
||||
}
|
||||
bool operator!=( const HashKey& other ) const {
|
||||
return !equal( other );
|
||||
}
|
||||
hash_t hash() const {
|
||||
return m_hash;
|
||||
}
|
||||
#if 0
|
||||
const char* c_str() const
|
||||
{
|
||||
return reinterpret_cast<const char*>(m_key.data());
|
||||
}
|
||||
const char* c_str() const {
|
||||
return reinterpret_cast<const char*>( m_key.data() );
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/// \brief Hash function to use with HashKey.
|
||||
struct HashKeyHasher
|
||||
{
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()(const HashKey<ub4_default_traits>& key) const
|
||||
{
|
||||
return key.hash();
|
||||
}
|
||||
typedef hash_t hash_type;
|
||||
hash_type operator()( const HashKey<ub4_default_traits>& key ) const {
|
||||
return key.hash();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,65 +1,62 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
#if defined(_DEBUG) || defined(DOXYGEN)
|
||||
#if defined( _DEBUG ) || defined( DOXYGEN )
|
||||
|
||||
#include "hashfunc.h"
|
||||
|
||||
namespace ExampleHashTable
|
||||
{
|
||||
void testStuff()
|
||||
{
|
||||
// HashTable example
|
||||
typedef HashTable<CopiedString, int, HashString> MyHashTable;
|
||||
MyHashTable hashtable;
|
||||
hashtable["bleh"] = 5;
|
||||
hashtable.insert("blah", 17);
|
||||
hashtable["foo"] = 99;
|
||||
hashtable.insert("bar", 23);
|
||||
void testStuff(){
|
||||
// HashTable example
|
||||
typedef HashTable<CopiedString, int, HashString> MyHashTable;
|
||||
MyHashTable hashtable;
|
||||
hashtable["bleh"] = 5;
|
||||
hashtable.insert( "blah", 17 );
|
||||
hashtable["foo"] = 99;
|
||||
hashtable.insert( "bar", 23 );
|
||||
|
||||
int bleh = (*hashtable.find("bleh")).value; // 5
|
||||
int blah = hashtable["blah"]; // 17
|
||||
hashtable.erase("foo");
|
||||
MyHashTable::iterator barIter = hashtable.find("bar");
|
||||
hashtable.erase(barIter);
|
||||
int bleh = ( *hashtable.find( "bleh" ) ).value; // 5
|
||||
int blah = hashtable["blah"]; // 17
|
||||
hashtable.erase( "foo" );
|
||||
MyHashTable::iterator barIter = hashtable.find( "bar" );
|
||||
hashtable.erase( barIter );
|
||||
|
||||
for(MyHashTable::iterator i = hashtable.begin(); i != hashtable.end(); ++i)
|
||||
{
|
||||
if((*i).key != "bleh")
|
||||
{
|
||||
++hashtable["count"]; // insertion does not invalidate iterators
|
||||
}
|
||||
}
|
||||
// end example
|
||||
}
|
||||
for ( MyHashTable::iterator i = hashtable.begin(); i != hashtable.end(); ++i )
|
||||
{
|
||||
if ( ( *i ).key != "bleh" ) {
|
||||
++hashtable["count"]; // insertion does not invalidate iterators
|
||||
}
|
||||
}
|
||||
// end example
|
||||
}
|
||||
|
||||
struct Always
|
||||
{
|
||||
Always()
|
||||
{
|
||||
testStuff();
|
||||
}
|
||||
} always;
|
||||
struct Always
|
||||
{
|
||||
Always(){
|
||||
testStuff();
|
||||
}
|
||||
} always;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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_HASHTABLE_H)
|
||||
#if !defined( INCLUDED_CONTAINER_HASHTABLE_H )
|
||||
#define INCLUDED_CONTAINER_HASHTABLE_H
|
||||
|
||||
#include <cstddef>
|
||||
@@ -30,151 +30,131 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
namespace HashTableDetail
|
||||
{
|
||||
inline std::size_t next_power_of_two(std::size_t size)
|
||||
{
|
||||
std::size_t result = 1;
|
||||
while(result < size)
|
||||
{
|
||||
result <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
inline std::size_t next_power_of_two( std::size_t size ){
|
||||
std::size_t result = 1;
|
||||
while ( result < size )
|
||||
{
|
||||
result <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct BucketNodeBase
|
||||
{
|
||||
BucketNodeBase* next;
|
||||
BucketNodeBase* prev;
|
||||
};
|
||||
struct BucketNodeBase
|
||||
{
|
||||
BucketNodeBase* next;
|
||||
BucketNodeBase* prev;
|
||||
};
|
||||
|
||||
inline void list_initialise(BucketNodeBase& self)
|
||||
{
|
||||
self.next = self.prev = &self;
|
||||
}
|
||||
inline void list_initialise( BucketNodeBase& self ){
|
||||
self.next = self.prev = &self;
|
||||
}
|
||||
|
||||
inline void list_swap(BucketNodeBase& self, BucketNodeBase& other)
|
||||
{
|
||||
BucketNodeBase tmp(self);
|
||||
if(other.next == &other)
|
||||
{
|
||||
list_initialise(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self = other;
|
||||
self.next->prev = self.prev->next = &self;
|
||||
}
|
||||
if(tmp.next == &self)
|
||||
{
|
||||
list_initialise(other);
|
||||
}
|
||||
else
|
||||
{
|
||||
other = tmp;
|
||||
other.next->prev = other.prev->next = &other;
|
||||
}
|
||||
}
|
||||
inline void list_swap( BucketNodeBase& self, BucketNodeBase& other ){
|
||||
BucketNodeBase tmp( self );
|
||||
if ( other.next == &other ) {
|
||||
list_initialise( self );
|
||||
}
|
||||
else
|
||||
{
|
||||
self = other;
|
||||
self.next->prev = self.prev->next = &self;
|
||||
}
|
||||
if ( tmp.next == &self ) {
|
||||
list_initialise( other );
|
||||
}
|
||||
else
|
||||
{
|
||||
other = tmp;
|
||||
other.next->prev = other.prev->next = &other;
|
||||
}
|
||||
}
|
||||
|
||||
inline void node_link(BucketNodeBase* node, BucketNodeBase* next)
|
||||
{
|
||||
node->next = next;
|
||||
node->prev = next->prev;
|
||||
next->prev = node;
|
||||
node->prev->next = node;
|
||||
}
|
||||
inline void node_unlink(BucketNodeBase* node)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
inline void node_link( BucketNodeBase* node, BucketNodeBase* next ){
|
||||
node->next = next;
|
||||
node->prev = next->prev;
|
||||
next->prev = node;
|
||||
node->prev->next = node;
|
||||
}
|
||||
inline void node_unlink( BucketNodeBase* node ){
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
template<typename Key, typename Value>
|
||||
struct KeyValue
|
||||
{
|
||||
const Key key;
|
||||
Value value;
|
||||
template<typename Key, typename Value>
|
||||
struct KeyValue
|
||||
{
|
||||
const Key key;
|
||||
Value value;
|
||||
|
||||
KeyValue(const Key& key_, const Value& value_)
|
||||
: key(key_), value(value_)
|
||||
{
|
||||
}
|
||||
};
|
||||
KeyValue( const Key& key_, const Value& value_ )
|
||||
: key( key_ ), value( value_ ){
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
struct BucketNode : public BucketNodeBase
|
||||
{
|
||||
Hash m_hash;
|
||||
KeyValue<Key, Value> m_value;
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
struct BucketNode : public BucketNodeBase
|
||||
{
|
||||
Hash m_hash;
|
||||
KeyValue<Key, Value> m_value;
|
||||
|
||||
BucketNode(Hash hash, const Key& key, const Value& value)
|
||||
: m_hash(hash), m_value(key, value)
|
||||
{
|
||||
}
|
||||
BucketNode* getNext() const
|
||||
{
|
||||
return static_cast<BucketNode*>(next);
|
||||
}
|
||||
BucketNode* getPrev() const
|
||||
{
|
||||
return static_cast<BucketNode*>(prev);
|
||||
}
|
||||
};
|
||||
BucketNode( Hash hash, const Key& key, const Value& value )
|
||||
: m_hash( hash ), m_value( key, value ){
|
||||
}
|
||||
BucketNode* getNext() const {
|
||||
return static_cast<BucketNode*>( next );
|
||||
}
|
||||
BucketNode* getPrev() const {
|
||||
return static_cast<BucketNode*>( prev );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
class BucketIterator
|
||||
{
|
||||
typedef BucketNode<Key, Value, Hash> Node;
|
||||
Node* m_node;
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
class BucketIterator
|
||||
{
|
||||
typedef BucketNode<Key, Value, Hash> Node;
|
||||
Node* m_node;
|
||||
|
||||
void increment()
|
||||
{
|
||||
m_node = m_node->getNext();
|
||||
}
|
||||
void increment(){
|
||||
m_node = m_node->getNext();
|
||||
}
|
||||
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef difference_type distance_type;
|
||||
typedef KeyValue<Key, Value> value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef difference_type distance_type;
|
||||
typedef KeyValue<Key, Value> value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
|
||||
BucketIterator(Node* node) : m_node(node)
|
||||
{
|
||||
}
|
||||
BucketIterator( Node* node ) : m_node( node ){
|
||||
}
|
||||
|
||||
Node* node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
Node* node(){
|
||||
return m_node;
|
||||
}
|
||||
|
||||
bool operator==(const BucketIterator& other) const
|
||||
{
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
bool operator!=(const BucketIterator& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
BucketIterator& operator++()
|
||||
{
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
BucketIterator operator++(int)
|
||||
{
|
||||
BucketIterator tmp = *this;
|
||||
increment();
|
||||
return tmp;
|
||||
}
|
||||
value_type& operator*() const
|
||||
{
|
||||
return m_node->m_value;
|
||||
}
|
||||
value_type* operator->() const
|
||||
{
|
||||
return &(operator*());
|
||||
}
|
||||
};
|
||||
bool operator==( const BucketIterator& other ) const {
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
bool operator!=( const BucketIterator& other ) const {
|
||||
return !operator==( other );
|
||||
}
|
||||
BucketIterator& operator++(){
|
||||
increment();
|
||||
return *this;
|
||||
}
|
||||
BucketIterator operator++( int ){
|
||||
BucketIterator tmp = *this;
|
||||
increment();
|
||||
return tmp;
|
||||
}
|
||||
value_type& operator*() const {
|
||||
return m_node->m_value;
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &( operator*() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -195,280 +175,236 @@ namespace HashTableDetail
|
||||
template<typename Key, typename Value, typename Hasher, typename KeyEqual = std::equal_to<Key> >
|
||||
class HashTable : private KeyEqual, private Hasher
|
||||
{
|
||||
typedef typename Hasher::hash_type hash_type;
|
||||
typedef HashTableDetail::KeyValue<Key, Value> KeyValue;
|
||||
typedef HashTableDetail::BucketNode<Key, Value, hash_type> BucketNode;
|
||||
typedef typename Hasher::hash_type hash_type;
|
||||
typedef HashTableDetail::KeyValue<Key, Value> KeyValue;
|
||||
typedef HashTableDetail::BucketNode<Key, Value, hash_type> BucketNode;
|
||||
|
||||
inline BucketNode* node_create(hash_type hash, const Key& key, const Value& value)
|
||||
{
|
||||
return new BucketNode(hash, key, value);
|
||||
}
|
||||
inline void node_destroy(BucketNode* node)
|
||||
{
|
||||
delete node;
|
||||
}
|
||||
inline BucketNode* node_create( hash_type hash, const Key& key, const Value& value ){
|
||||
return new BucketNode( hash, key, value );
|
||||
}
|
||||
inline void node_destroy( BucketNode* node ){
|
||||
delete node;
|
||||
}
|
||||
|
||||
typedef BucketNode* Bucket;
|
||||
typedef BucketNode* Bucket;
|
||||
|
||||
static Bucket* buckets_new(std::size_t count)
|
||||
{
|
||||
Bucket* buckets = new Bucket[count];
|
||||
std::uninitialized_fill(buckets, buckets + count, Bucket(0));
|
||||
return buckets;
|
||||
}
|
||||
static void buckets_delete(Bucket* buckets)
|
||||
{
|
||||
delete[] buckets;
|
||||
}
|
||||
static Bucket* buckets_new( std::size_t count ){
|
||||
Bucket* buckets = new Bucket[count];
|
||||
std::uninitialized_fill( buckets, buckets + count, Bucket( 0 ) );
|
||||
return buckets;
|
||||
}
|
||||
static void buckets_delete( Bucket* buckets ){
|
||||
delete[] buckets;
|
||||
}
|
||||
|
||||
std::size_t m_bucketCount;
|
||||
Bucket* m_buckets;
|
||||
std::size_t m_size;
|
||||
HashTableDetail::BucketNodeBase m_list;
|
||||
std::size_t m_bucketCount;
|
||||
Bucket* m_buckets;
|
||||
std::size_t m_size;
|
||||
HashTableDetail::BucketNodeBase m_list;
|
||||
|
||||
BucketNode* getFirst()
|
||||
{
|
||||
return static_cast<BucketNode*>(m_list.next);
|
||||
}
|
||||
BucketNode* getLast()
|
||||
{
|
||||
return static_cast<BucketNode*>(&m_list);
|
||||
}
|
||||
BucketNode* getFirst(){
|
||||
return static_cast<BucketNode*>( m_list.next );
|
||||
}
|
||||
BucketNode* getLast(){
|
||||
return static_cast<BucketNode*>( &m_list );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef KeyValue value_type;
|
||||
typedef HashTableDetail::BucketIterator<Key, Value, hash_type> iterator;
|
||||
typedef KeyValue value_type;
|
||||
typedef HashTableDetail::BucketIterator<Key, Value, hash_type> iterator;
|
||||
|
||||
private:
|
||||
|
||||
void initialise()
|
||||
{
|
||||
list_initialise(m_list);
|
||||
}
|
||||
hash_type hashKey(const Key& key)
|
||||
{
|
||||
return Hasher::operator()(key);
|
||||
}
|
||||
void initialise(){
|
||||
list_initialise( m_list );
|
||||
}
|
||||
hash_type hashKey( const Key& key ){
|
||||
return Hasher::operator()( key );
|
||||
}
|
||||
|
||||
std::size_t getBucketId(hash_type hash) const
|
||||
{
|
||||
return hash & (m_bucketCount - 1);
|
||||
}
|
||||
Bucket& getBucket(hash_type hash)
|
||||
{
|
||||
return m_buckets[getBucketId(hash)];
|
||||
}
|
||||
BucketNode* bucket_find(Bucket bucket, hash_type hash, const Key& key)
|
||||
{
|
||||
std::size_t bucketId = getBucketId(hash);
|
||||
for(iterator i(bucket); i != end(); ++i)
|
||||
{
|
||||
hash_type nodeHash = i.node()->m_hash;
|
||||
std::size_t getBucketId( hash_type hash ) const {
|
||||
return hash & ( m_bucketCount - 1 );
|
||||
}
|
||||
Bucket& getBucket( hash_type hash ){
|
||||
return m_buckets[getBucketId( hash )];
|
||||
}
|
||||
BucketNode* bucket_find( Bucket bucket, hash_type hash, const Key& key ){
|
||||
std::size_t bucketId = getBucketId( hash );
|
||||
for ( iterator i( bucket ); i != end(); ++i )
|
||||
{
|
||||
hash_type nodeHash = i.node()->m_hash;
|
||||
|
||||
if(getBucketId(nodeHash) != bucketId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ( getBucketId( nodeHash ) != bucketId ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(nodeHash == hash && KeyEqual::operator()((*i).key, key))
|
||||
{
|
||||
return i.node();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
BucketNode* bucket_insert(Bucket& bucket, BucketNode* node)
|
||||
{
|
||||
// link node into list
|
||||
node_link(node, bucket_next(bucket));
|
||||
bucket = node;
|
||||
return node;
|
||||
}
|
||||
BucketNode* bucket_next(Bucket& bucket)
|
||||
{
|
||||
Bucket* end = m_buckets + m_bucketCount;
|
||||
for(Bucket* i = &bucket; i != end; ++i)
|
||||
{
|
||||
if(*i != 0)
|
||||
{
|
||||
return *i;
|
||||
}
|
||||
}
|
||||
return getLast();
|
||||
}
|
||||
if ( nodeHash == hash && KeyEqual::operator()( ( *i ).key, key ) ) {
|
||||
return i.node();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
BucketNode* bucket_insert( Bucket& bucket, BucketNode* node ){
|
||||
// link node into list
|
||||
node_link( node, bucket_next( bucket ) );
|
||||
bucket = node;
|
||||
return node;
|
||||
}
|
||||
BucketNode* bucket_next( Bucket& bucket ){
|
||||
Bucket* end = m_buckets + m_bucketCount;
|
||||
for ( Bucket* i = &bucket; i != end; ++i )
|
||||
{
|
||||
if ( *i != 0 ) {
|
||||
return *i;
|
||||
}
|
||||
}
|
||||
return getLast();
|
||||
}
|
||||
|
||||
void buckets_resize(std::size_t count)
|
||||
{
|
||||
BucketNode* first = getFirst();
|
||||
BucketNode* last = getLast();
|
||||
void buckets_resize( std::size_t count ){
|
||||
BucketNode* first = getFirst();
|
||||
BucketNode* last = getLast();
|
||||
|
||||
buckets_delete(m_buckets);
|
||||
buckets_delete( m_buckets );
|
||||
|
||||
m_bucketCount = count;
|
||||
m_bucketCount = count;
|
||||
|
||||
m_buckets = buckets_new(m_bucketCount);
|
||||
initialise();
|
||||
m_buckets = buckets_new( m_bucketCount );
|
||||
initialise();
|
||||
|
||||
for(BucketNode* i = first; i != last;)
|
||||
{
|
||||
BucketNode* node = i;
|
||||
i = i->getNext();
|
||||
bucket_insert(getBucket((*node).m_hash), node);
|
||||
}
|
||||
}
|
||||
void size_increment()
|
||||
{
|
||||
if(m_size == m_bucketCount)
|
||||
{
|
||||
buckets_resize(m_bucketCount == 0 ? 8 : m_bucketCount << 1);
|
||||
}
|
||||
++m_size;
|
||||
}
|
||||
void size_decrement()
|
||||
{
|
||||
--m_size;
|
||||
}
|
||||
for ( BucketNode* i = first; i != last; )
|
||||
{
|
||||
BucketNode* node = i;
|
||||
i = i->getNext();
|
||||
bucket_insert( getBucket( ( *node ).m_hash ), node );
|
||||
}
|
||||
}
|
||||
void size_increment(){
|
||||
if ( m_size == m_bucketCount ) {
|
||||
buckets_resize( m_bucketCount == 0 ? 8 : m_bucketCount << 1 );
|
||||
}
|
||||
++m_size;
|
||||
}
|
||||
void size_decrement(){
|
||||
--m_size;
|
||||
}
|
||||
|
||||
HashTable(const HashTable& other);
|
||||
HashTable& operator=(const HashTable& other);
|
||||
HashTable( const HashTable& other );
|
||||
HashTable& operator=( const HashTable& other );
|
||||
public:
|
||||
HashTable() : m_bucketCount(0), m_buckets(0), m_size(0)
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
HashTable(std::size_t bucketCount) : m_bucketCount(HashTableDetail::next_power_of_two(bucketCount)), m_buckets(buckets_new(m_bucketCount)), m_size(0)
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
~HashTable()
|
||||
{
|
||||
for(BucketNode* i = getFirst(); i != getLast();)
|
||||
{
|
||||
BucketNode* node = i;
|
||||
i = i->getNext();
|
||||
node_destroy(node);
|
||||
}
|
||||
buckets_delete(m_buckets);
|
||||
}
|
||||
HashTable() : m_bucketCount( 0 ), m_buckets( 0 ), m_size( 0 ){
|
||||
initialise();
|
||||
}
|
||||
HashTable( std::size_t bucketCount ) : m_bucketCount( HashTableDetail::next_power_of_two( bucketCount ) ), m_buckets( buckets_new( m_bucketCount ) ), m_size( 0 ){
|
||||
initialise();
|
||||
}
|
||||
~HashTable(){
|
||||
for ( BucketNode* i = getFirst(); i != getLast(); )
|
||||
{
|
||||
BucketNode* node = i;
|
||||
i = i->getNext();
|
||||
node_destroy( node );
|
||||
}
|
||||
buckets_delete( m_buckets );
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(getFirst());
|
||||
}
|
||||
iterator end()
|
||||
{
|
||||
return iterator(getLast());
|
||||
}
|
||||
iterator begin(){
|
||||
return iterator( getFirst() );
|
||||
}
|
||||
iterator end(){
|
||||
return iterator( getLast() );
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
bool empty() const {
|
||||
return m_size == 0;
|
||||
}
|
||||
std::size_t size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/// \brief Returns an iterator pointing to the value associated with \p key if it is contained by the hash-table, else \c end().
|
||||
iterator find(const Key& key)
|
||||
{
|
||||
hash_type hash = hashKey(key);
|
||||
if(m_bucketCount != 0)
|
||||
{
|
||||
Bucket bucket = getBucket(hash);
|
||||
if(bucket != 0)
|
||||
{
|
||||
BucketNode* node = bucket_find(bucket, hash, key);
|
||||
if(node != 0)
|
||||
{
|
||||
return iterator(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
/// \brief Adds \p value to the hash-table associated with \p key if it does not exist.
|
||||
iterator insert(const Key& key, const Value& value)
|
||||
{
|
||||
hash_type hash = hashKey(key);
|
||||
if(m_bucketCount != 0)
|
||||
{
|
||||
Bucket& bucket = getBucket(hash);
|
||||
if(bucket != 0)
|
||||
{
|
||||
BucketNode* node = bucket_find(bucket, hash, key);
|
||||
if(node != 0)
|
||||
{
|
||||
return iterator(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// \brief Returns an iterator pointing to the value associated with \p key if it is contained by the hash-table, else \c end().
|
||||
iterator find( const Key& key ){
|
||||
hash_type hash = hashKey( key );
|
||||
if ( m_bucketCount != 0 ) {
|
||||
Bucket bucket = getBucket( hash );
|
||||
if ( bucket != 0 ) {
|
||||
BucketNode* node = bucket_find( bucket, hash, key );
|
||||
if ( node != 0 ) {
|
||||
return iterator( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_increment();
|
||||
return iterator(bucket_insert(getBucket(hash), node_create(hash, key, value)));
|
||||
}
|
||||
return end();
|
||||
}
|
||||
/// \brief Adds \p value to the hash-table associated with \p key if it does not exist.
|
||||
iterator insert( const Key& key, const Value& value ){
|
||||
hash_type hash = hashKey( key );
|
||||
if ( m_bucketCount != 0 ) {
|
||||
Bucket& bucket = getBucket( hash );
|
||||
if ( bucket != 0 ) {
|
||||
BucketNode* node = bucket_find( bucket, hash, key );
|
||||
if ( node != 0 ) {
|
||||
return iterator( node );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Removes the value pointed to by \p i from the hash-table.
|
||||
///
|
||||
/// \p i must be a deferenceable iterator into the hash-table.
|
||||
void erase(iterator i)
|
||||
{
|
||||
Bucket& bucket = getBucket(i.node()->m_hash);
|
||||
BucketNode* node = i.node();
|
||||
size_increment();
|
||||
return iterator( bucket_insert( getBucket( hash ), node_create( hash, key, value ) ) );
|
||||
}
|
||||
|
||||
// if this was the last node in the bucket
|
||||
if(bucket == node)
|
||||
{
|
||||
bucket = (node->getNext() == getLast() || &getBucket(node->getNext()->m_hash) != &bucket) ? 0 : node->getNext();
|
||||
}
|
||||
/// \brief Removes the value pointed to by \p i from the hash-table.
|
||||
///
|
||||
/// \p i must be a deferenceable iterator into the hash-table.
|
||||
void erase( iterator i ){
|
||||
Bucket& bucket = getBucket( i.node()->m_hash );
|
||||
BucketNode* node = i.node();
|
||||
|
||||
node_unlink(node);
|
||||
ASSERT_MESSAGE(node != 0, "tried to erase a non-existent key/value");
|
||||
node_destroy(node);
|
||||
// if this was the last node in the bucket
|
||||
if ( bucket == node ) {
|
||||
bucket = ( node->getNext() == getLast() || &getBucket( node->getNext()->m_hash ) != &bucket ) ? 0 : node->getNext();
|
||||
}
|
||||
|
||||
size_decrement();
|
||||
}
|
||||
node_unlink( node );
|
||||
ASSERT_MESSAGE( node != 0, "tried to erase a non-existent key/value" );
|
||||
node_destroy( node );
|
||||
|
||||
/// \brief Returns the value identified by \p key if it is contained by the hash-table, else inserts and returns a new default-constructed value associated with \p key.
|
||||
Value& operator[](const Key& key)
|
||||
{
|
||||
hash_type hash = hashKey(key);
|
||||
if(m_bucketCount != 0)
|
||||
{
|
||||
Bucket& bucket = getBucket(hash);
|
||||
if(bucket != 0)
|
||||
{
|
||||
BucketNode* node = bucket_find(bucket, hash, key);
|
||||
if(node != 0)
|
||||
{
|
||||
return node->m_value.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_increment();
|
||||
return bucket_insert(getBucket(hash), node_create(hash, key, Value()))->m_value.value;
|
||||
}
|
||||
/// \brief Removes the value associated with \p key from the hash-table.
|
||||
void erase(const Key& key)
|
||||
{
|
||||
erase(find(key));
|
||||
}
|
||||
/// \brief Swaps the contents of the hash-table with \p other.
|
||||
void swap(HashTable& other)
|
||||
{
|
||||
std::swap(m_buckets, other.m_buckets);
|
||||
std::swap(m_bucketCount, other.m_bucketCount);
|
||||
std::swap(m_size, other.m_size);
|
||||
HashTableDetail::list_swap(m_list, other.m_list);
|
||||
}
|
||||
/// \brief Removes all values from the hash-table.
|
||||
void clear()
|
||||
{
|
||||
HashTable tmp;
|
||||
tmp.swap(*this);
|
||||
}
|
||||
size_decrement();
|
||||
}
|
||||
|
||||
/// \brief Returns the value identified by \p key if it is contained by the hash-table, else inserts and returns a new default-constructed value associated with \p key.
|
||||
Value& operator[]( const Key& key ){
|
||||
hash_type hash = hashKey( key );
|
||||
if ( m_bucketCount != 0 ) {
|
||||
Bucket& bucket = getBucket( hash );
|
||||
if ( bucket != 0 ) {
|
||||
BucketNode* node = bucket_find( bucket, hash, key );
|
||||
if ( node != 0 ) {
|
||||
return node->m_value.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
size_increment();
|
||||
return bucket_insert( getBucket( hash ), node_create( hash, key, Value() ) )->m_value.value;
|
||||
}
|
||||
/// \brief Removes the value associated with \p key from the hash-table.
|
||||
void erase( const Key& key ){
|
||||
erase( find( key ) );
|
||||
}
|
||||
/// \brief Swaps the contents of the hash-table with \p other.
|
||||
void swap( HashTable& other ){
|
||||
std::swap( m_buckets, other.m_buckets );
|
||||
std::swap( m_bucketCount, other.m_bucketCount );
|
||||
std::swap( m_size, other.m_size );
|
||||
HashTableDetail::list_swap( m_list, other.m_list );
|
||||
}
|
||||
/// \brief Removes all values from the hash-table.
|
||||
void clear(){
|
||||
HashTable tmp;
|
||||
tmp.swap( *this );
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
#include "stack.h"
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
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 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.
|
||||
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
|
||||
*/
|
||||
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)
|
||||
#if !defined( INCLUDED_CONTAINER_STACK_H )
|
||||
#define INCLUDED_CONTAINER_STACK_H
|
||||
|
||||
#include "memory/allocator.h"
|
||||
@@ -36,204 +36,176 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
template<typename Type>
|
||||
class Stack : public DefaultAllocator<Type>
|
||||
{
|
||||
typedef DefaultAllocator<Type> Allocator;
|
||||
typedef DefaultAllocator<Type> Allocator;
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 4,
|
||||
};
|
||||
enum
|
||||
{
|
||||
DEFAULT_CAPACITY = 4,
|
||||
};
|
||||
|
||||
typedef Type* pointer;
|
||||
typedef const Type* const_pointer;
|
||||
typedef Type* pointer;
|
||||
typedef const Type* const_pointer;
|
||||
|
||||
public:
|
||||
typedef const_pointer const_iterator;
|
||||
typedef const_pointer const_iterator;
|
||||
private:
|
||||
|
||||
pointer m_data;
|
||||
pointer m_end;
|
||||
std::size_t m_capacity;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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();
|
||||
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();
|
||||
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;
|
||||
}
|
||||
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());
|
||||
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);
|
||||
}
|
||||
/// \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
|
||||
|
||||
Reference in New Issue
Block a user