my own uncrustify run

This commit is contained in:
Rudolf Polzer
2012-03-27 12:03:21 +02:00
parent 203343b01a
commit e4287c28bb
1056 changed files with 194610 additions and 205971 deletions

View File

@@ -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 );
}
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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();
}
};

View File

@@ -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"

View File

@@ -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 );
}
}
};

View File

@@ -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"

View File

@@ -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();
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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