Commit 95cefe5f by Paolo Carlini Committed by Paolo Carlini

hashtable_policy.h: Uglify all the names.

2006-09-19  Paolo Carlini  <pcarlini@suse.de>

	* include/tr1/hashtable_policy.h: Uglify all the names.
	* include/tr1/hashtable: Likewise.
	* include/tr1/unordered_map: Likewise.
	* include/tr1/unordered_set: Likewise.
	* include/tr1/functional: Uglify struct hash names.
	* include/tr1/cmath: Uglify namespace detail to __detail.

From-SVN: r117052
parent b5387733
2006-09-19 Paolo Carlini <pcarlini@suse.de>
* include/tr1/hashtable_policy.h: Uglify all the names.
* include/tr1/hashtable: Likewise.
* include/tr1/unordered_map: Likewise.
* include/tr1/unordered_set: Likewise.
* include/tr1/functional: Uglify struct hash names.
* include/tr1/cmath: Uglify namespace detail to __detail.
2006-09-18 Benjamin Kosnik <bkoz@redhat.com> 2006-09-18 Benjamin Kosnik <bkoz@redhat.com>
* testsuite/util/regression/res_mng: Remove. * testsuite/util/regression/res_mng: Remove.
......
...@@ -368,21 +368,23 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -368,21 +368,23 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
using std::atan; using std::atan;
// Workaround for c++/21682. // Workaround for c++/21682.
namespace detail namespace __detail
{ {
template<typename _Tp, typename _Up> template<typename _Tp, typename _Up>
inline typename __gnu_cxx::__enable_if<std::__is_floating<_Tp>::__value inline typename
__gnu_cxx::__enable_if<std::__is_floating<_Tp>::__value
|| std::__is_floating<_Up>::__value, || std::__is_floating<_Up>::__value,
typename std::tr1::__promote_2<_Tp, _Up>::__type>::__type typename
std::tr1::__promote_2<_Tp, _Up>::__type>::__type
atan2(_Tp __y, _Up __x) atan2(_Tp __y, _Up __x)
{ {
typedef typename std::tr1::__promote_2<_Tp, _Up>::__type __type; typedef typename std::tr1::__promote_2<_Tp, _Up>::__type __type;
return std::atan2(__type(__y), __type(__x)); return std::atan2(__type(__y), __type(__x));
} }
} // namespace detail } // namespace __detail
using std::atan2; using std::atan2;
using detail::atan2; using __detail::atan2;
inline float inline float
atanh(float __x) atanh(float __x)
......
// TR1 functional header -*- C++ -*- // TR1 functional header -*- C++ -*-
// Copyright (C) 2004, 2005 Free Software Foundation, Inc. // Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -1100,37 +1100,37 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1100,37 +1100,37 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
template<typename T> template<typename T>
struct hash; struct hash;
#define tr1_hashtable_define_trivial_hash(T) \ #define _TR1_hashtable_define_trivial_hash(_Tp) \
template<> \ template<> \
struct hash<T> \ struct hash<_Tp> \
: public std::unary_function<T, std::size_t> \ : public std::unary_function<_Tp, std::size_t> \
{ \ { \
std::size_t \ std::size_t \
operator()(T val) const \ operator()(_Tp __val) const \
{ return static_cast<std::size_t>(val); } \ { return static_cast<std::size_t>(__val); } \
} }
tr1_hashtable_define_trivial_hash(bool); _TR1_hashtable_define_trivial_hash(bool);
tr1_hashtable_define_trivial_hash(char); _TR1_hashtable_define_trivial_hash(char);
tr1_hashtable_define_trivial_hash(signed char); _TR1_hashtable_define_trivial_hash(signed char);
tr1_hashtable_define_trivial_hash(unsigned char); _TR1_hashtable_define_trivial_hash(unsigned char);
tr1_hashtable_define_trivial_hash(wchar_t); _TR1_hashtable_define_trivial_hash(wchar_t);
tr1_hashtable_define_trivial_hash(short); _TR1_hashtable_define_trivial_hash(short);
tr1_hashtable_define_trivial_hash(int); _TR1_hashtable_define_trivial_hash(int);
tr1_hashtable_define_trivial_hash(long); _TR1_hashtable_define_trivial_hash(long);
tr1_hashtable_define_trivial_hash(unsigned short); _TR1_hashtable_define_trivial_hash(unsigned short);
tr1_hashtable_define_trivial_hash(unsigned int); _TR1_hashtable_define_trivial_hash(unsigned int);
tr1_hashtable_define_trivial_hash(unsigned long); _TR1_hashtable_define_trivial_hash(unsigned long);
#undef tr1_hashtable_define_trivial_hash #undef _TR1_hashtable_define_trivial_hash
template<typename T> template<typename _Tp>
struct hash<T*> struct hash<_Tp*>
: public std::unary_function<T*, std::size_t> : public std::unary_function<_Tp*, std::size_t>
{ {
std::size_t std::size_t
operator()(T* p) const operator()(_Tp* __p) const
{ return reinterpret_cast<std::size_t>(p); } { return reinterpret_cast<std::size_t>(__p); }
}; };
// Fowler / Noll / Vo (FNV) Hash (type FNV-1a) // Fowler / Noll / Vo (FNV) Hash (type FNV-1a)
...@@ -1138,47 +1138,48 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1138,47 +1138,48 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// Dummy generic implementation (for sizeof(size_t) != 4, 8). // Dummy generic implementation (for sizeof(size_t) != 4, 8).
template<std::size_t = sizeof(std::size_t)> template<std::size_t = sizeof(std::size_t)>
struct Fnv_hash struct _Fnv_hash
{ {
static std::size_t static std::size_t
hash(const char* first, std::size_t length) hash(const char* __first, std::size_t __length)
{ {
std::size_t result = 0; std::size_t __result = 0;
for (; length > 0; --length) for (; __length > 0; --__length)
result = (result * 131) + *first++; __result = (__result * 131) + *__first++;
return result; return __result;
} }
}; };
template<> template<>
struct Fnv_hash<4> struct _Fnv_hash<4>
{ {
static std::size_t static std::size_t
hash(const char* first, std::size_t length) hash(const char* __first, std::size_t __length)
{ {
std::size_t result = static_cast<std::size_t>(2166136261UL); std::size_t __result = static_cast<std::size_t>(2166136261UL);
for (; length > 0; --length) for (; __length > 0; --__length)
{ {
result ^= (std::size_t)*first++; __result ^= (std::size_t)*__first++;
result *= 16777619UL; __result *= 16777619UL;
} }
return result; return __result;
} }
}; };
template<> template<>
struct Fnv_hash<8> struct _Fnv_hash<8>
{ {
static std::size_t static std::size_t
hash(const char* first, std::size_t length) hash(const char* __first, std::size_t __length)
{ {
std::size_t result = static_cast<std::size_t>(14695981039346656037ULL); std::size_t __result =
for (; length > 0; --length) static_cast<std::size_t>(14695981039346656037ULL);
for (; __length > 0; --__length)
{ {
result ^= (std::size_t)*first++; __result ^= (std::size_t)*__first++;
result *= 1099511628211ULL; __result *= 1099511628211ULL;
} }
return result; return __result;
} }
}; };
...@@ -1190,8 +1191,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1190,8 +1191,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: public std::unary_function<std::string, std::size_t> : public std::unary_function<std::string, std::size_t>
{ {
std::size_t std::size_t
operator()(const std::string& s) const operator()(const std::string& __s) const
{ return Fnv_hash<>::hash(s.data(), s.length()); } { return _Fnv_hash<>::hash(__s.data(), __s.length()); }
}; };
#ifdef _GLIBCXX_USE_WCHAR_T #ifdef _GLIBCXX_USE_WCHAR_T
...@@ -1200,10 +1201,10 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1200,10 +1201,10 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: public std::unary_function<std::wstring, std::size_t> : public std::unary_function<std::wstring, std::size_t>
{ {
std::size_t std::size_t
operator()(const std::wstring& s) const operator()(const std::wstring& __s) const
{ {
return Fnv_hash<>::hash(reinterpret_cast<const char*>(s.data()), return _Fnv_hash<>::hash(reinterpret_cast<const char*>(__s.data()),
s.length() * sizeof(wchar_t)); __s.length() * sizeof(wchar_t));
} }
}; };
#endif #endif
...@@ -1213,15 +1214,15 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1213,15 +1214,15 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: public std::unary_function<float, std::size_t> : public std::unary_function<float, std::size_t>
{ {
std::size_t std::size_t
operator()(float fval) const operator()(float __fval) const
{ {
std::size_t result = 0; std::size_t __result = 0;
// 0 and -0 both hash to zero. // 0 and -0 both hash to zero.
if (fval != 0.0f) if (__fval != 0.0f)
result = Fnv_hash<>::hash(reinterpret_cast<const char*>(&fval), __result = _Fnv_hash<>::hash(reinterpret_cast<const char*>(&__fval),
sizeof(fval)); sizeof(__fval));
return result; return __result;
} }
}; };
...@@ -1230,15 +1231,15 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1230,15 +1231,15 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: public std::unary_function<double, std::size_t> : public std::unary_function<double, std::size_t>
{ {
std::size_t std::size_t
operator()(double dval) const operator()(double __dval) const
{ {
std::size_t result = 0; std::size_t __result = 0;
// 0 and -0 both hash to zero. // 0 and -0 both hash to zero.
if (dval != 0.0) if (__dval != 0.0)
result = Fnv_hash<>::hash(reinterpret_cast<const char*>(&dval), __result = _Fnv_hash<>::hash(reinterpret_cast<const char*>(&__dval),
sizeof(dval)); sizeof(__dval));
return result; return __result;
} }
}; };
...@@ -1249,29 +1250,30 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1249,29 +1250,30 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: public std::unary_function<long double, std::size_t> : public std::unary_function<long double, std::size_t>
{ {
std::size_t std::size_t
operator()(long double ldval) const operator()(long double __ldval) const
{ {
std::size_t result = 0; std::size_t __result = 0;
int exponent; int __exponent;
ldval = std::frexp(ldval, &exponent); __ldval = std::frexp(__ldval, &__exponent);
ldval = ldval < 0.0l ? -(ldval + 0.5l) : ldval; __ldval = __ldval < 0.0l ? -(__ldval + 0.5l) : __ldval;
const long double mult = std::numeric_limits<std::size_t>::max() + 1.0l; const long double __mult =
ldval *= mult; std::numeric_limits<std::size_t>::max() + 1.0l;
__ldval *= __mult;
// Try to use all the bits of the mantissa (really necessary only // Try to use all the bits of the mantissa (really necessary only
// on 32-bit targets, at least for 80-bit floating point formats). // on 32-bit targets, at least for 80-bit floating point formats).
const std::size_t hibits = (std::size_t)ldval; const std::size_t __hibits = (std::size_t)__ldval;
ldval = (ldval - (long double)hibits) * mult; __ldval = (__ldval - (long double)__hibits) * __mult;
const std::size_t coeff = const std::size_t __coeff =
(std::numeric_limits<std::size_t>::max() (std::numeric_limits<std::size_t>::max()
/ std::numeric_limits<long double>::max_exponent); / std::numeric_limits<long double>::max_exponent);
result = hibits + (std::size_t)ldval + coeff * exponent; __result = __hibits + (std::size_t)__ldval + __coeff * __exponent;
return result; return __result;
} }
}; };
......
...@@ -66,40 +66,40 @@ namespace std ...@@ -66,40 +66,40 @@ namespace std
{ {
_GLIBCXX_BEGIN_NAMESPACE(tr1) _GLIBCXX_BEGIN_NAMESPACE(tr1)
// Class template hashtable, class definition. // Class template _Hashtable, class definition.
// Meaning of class template hashtable's template parameters // Meaning of class template _Hashtable's template parameters
// Key and Value: arbitrary CopyConstructible types. // _Key and _Value: arbitrary CopyConstructible types.
// Allocator: an allocator type ([lib.allocator.requirements]) whose // _Allocator: an allocator type ([lib.allocator.requirements]) whose
// value type is Value. // value type is Value.
// ExtractKey: function object that takes a object of type Value // _ExtractKey: function object that takes a object of type Value
// and returns a value of type Key. // and returns a value of type _Key.
// Equal: function object that takes two objects of type k and returns // _Equal: function object that takes two objects of type k and returns
// a bool-like value that is true if the two objects are considered equal. // a bool-like value that is true if the two objects are considered equal.
// H1: the hash function. A unary function object with argument type // _H1: the hash function. A unary function object with argument type
// Key and result type size_t. Return values should be distributed // Key and result type size_t. Return values should be distributed
// over the entire range [0, numeric_limits<size_t>:::max()]. // over the entire range [0, numeric_limits<size_t>:::max()].
// H2: the range-hashing function (in the terminology of Tavori and // _H2: the range-hashing function (in the terminology of Tavori and
// Dreizin). A binary function object whose argument types and result // Dreizin). A binary function object whose argument types and result
// type are all size_t. Given arguments r and N, the return value is // type are all size_t. Given arguments r and N, the return value is
// in the range [0, N). // in the range [0, N).
// H: the ranged hash function (Tavori and Dreizin). A binary function // _Hash: the ranged hash function (Tavori and Dreizin). A binary function
// whose argument types are Key and size_t and whose result type is // whose argument types are _Key and size_t and whose result type is
// size_t. Given arguments k and N, the return value is in the range // size_t. Given arguments k and N, the return value is in the range
// [0, N). Default: h(k, N) = h2(h1(k), N). If H is anything other // [0, N). Default: hash(k, N) = h2(h1(k), N). If _Hash is anything other
// than the default, H1 and H2 are ignored. // than the default, _H1 and _H2 are ignored.
// RehashPolicy: Policy class with three members, all of which govern // _RehashPolicy: Policy class with three members, all of which govern
// the bucket count. n_bkt(n) returns a bucket count no smaller // the bucket count. _M_next_bkt(n) returns a bucket count no smaller
// than n. bkt_for_elements(n) returns a bucket count appropriate // than n. _M_bkt_for_elements(n) returns a bucket count appropriate
// for an element count of n. need_rehash(n_bkt, n_elt, n_ins) // for an element count of n. _M_need_rehash(n_bkt, n_elt, n_ins)
// determines whether, if the current bucket count is n_bkt and the // determines whether, if the current bucket count is n_bkt and the
// current element count is n_elt, we need to increase the bucket // current element count is n_elt, we need to increase the bucket
// count. If so, returns make_pair(true, n), where n is the new // count. If so, returns make_pair(true, n), where n is the new
...@@ -108,151 +108,159 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -108,151 +108,159 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// ??? Right now it is hard-wired that the number of buckets never // ??? Right now it is hard-wired that the number of buckets never
// shrinks. Should we allow RehashPolicy to change that? // shrinks. Should we allow RehashPolicy to change that?
// cache_hash_code: bool. true if we store the value of the hash // __cache_hash_code: bool. true if we store the value of the hash
// function along with the value. This is a time-space tradeoff. // function along with the value. This is a time-space tradeoff.
// Storing it may improve lookup speed by reducing the number of times // Storing it may improve lookup speed by reducing the number of times
// we need to call the Equal function. // we need to call the Equal function.
// constant_iterators: bool. true if iterator and const_iterator are // __constant_iterators: bool. true if iterator and const_iterator are
// both constant iterator types. This is true for unordered_set and // both constant iterator types. This is true for unordered_set and
// unordered_multiset, false for unordered_map and unordered_multimap. // unordered_multiset, false for unordered_map and unordered_multimap.
// unique_keys: bool. true if the return value of hashtable::count(k) // __unique_keys: bool. true if the return value of _Hashtable::count(k)
// is always at most one, false if it may be an arbitrary number. This // is always at most one, false if it may be an arbitrary number. This
// true for unordered_set and unordered_map, false for unordered_multiset // true for unordered_set and unordered_map, false for unordered_multiset
// and unordered_multimap. // and unordered_multimap.
template<typename Key, typename Value, typename Allocator, template<typename _Key, typename _Value, typename _Allocator,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename _H1, typename _H2, typename _Hash,
typename RehashPolicy, typename _RehashPolicy,
bool cache_hash_code, bool __cache_hash_code,
bool constant_iterators, bool __constant_iterators,
bool unique_keys> bool __unique_keys>
class hashtable class _Hashtable
: public detail::rehash_base<RehashPolicy, : public __detail::_Rehash_base<_RehashPolicy,
hashtable<Key, Value, Allocator, ExtractKey, _Hashtable<_Key, _Value, _Allocator,
Equal, H1, H2, H, RehashPolicy, _ExtractKey,
cache_hash_code, constant_iterators, _Equal, _H1, _H2, _Hash,
unique_keys> >, _RehashPolicy,
public detail::hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, __cache_hash_code,
cache_hash_code>, __constant_iterators,
public detail::map_base<Key, Value, ExtractKey, unique_keys, __unique_keys> >,
hashtable<Key, Value, Allocator, ExtractKey, public __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
Equal, H1, H2, H, RehashPolicy, _H1, _H2, _Hash, __cache_hash_code>,
cache_hash_code, constant_iterators, public __detail::_Map_base<_Key, _Value, _ExtractKey, __unique_keys,
unique_keys> > _Hashtable<_Key, _Value, _Allocator,
_ExtractKey,
_Equal, _H1, _H2, _Hash,
_RehashPolicy,
__cache_hash_code,
__constant_iterators,
__unique_keys> >
{ {
public: public:
typedef Allocator allocator_type; typedef _Allocator allocator_type;
typedef Value value_type; typedef _Value value_type;
typedef Key key_type; typedef _Key key_type;
typedef Equal key_equal; typedef _Equal key_equal;
// mapped_type, if present, comes from map_base. // mapped_type, if present, comes from map_base.
// hasher, if present, comes from hash_code_base. // hasher, if present, comes from hash_code_base.
typedef typename Allocator::difference_type difference_type; typedef typename _Allocator::difference_type difference_type;
typedef typename Allocator::size_type size_type; typedef typename _Allocator::size_type size_type;
typedef typename Allocator::reference reference; typedef typename _Allocator::reference reference;
typedef typename Allocator::const_reference const_reference; typedef typename _Allocator::const_reference const_reference;
typedef detail::node_iterator<value_type, constant_iterators, typedef __detail::_Node_iterator<value_type, __constant_iterators,
cache_hash_code> __cache_hash_code>
local_iterator; local_iterator;
typedef detail::node_const_iterator<value_type, constant_iterators, typedef __detail::_Node_const_iterator<value_type,
cache_hash_code> __constant_iterators,
__cache_hash_code>
const_local_iterator; const_local_iterator;
typedef detail::hashtable_iterator<value_type, constant_iterators, typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
cache_hash_code> __cache_hash_code>
iterator; iterator;
typedef detail::hashtable_const_iterator<value_type, constant_iterators, typedef __detail::_Hashtable_const_iterator<value_type,
cache_hash_code> __constant_iterators,
__cache_hash_code>
const_iterator; const_iterator;
template<typename K, typename Pair, typename Hashtable> template<typename _Key2, typename _Pair, typename _Hashtable>
friend struct detail::map_base; friend struct __detail::_Map_base;
private: private:
typedef detail::hash_node<Value, cache_hash_code> node; typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
typedef typename Allocator::template rebind<node>::other typedef typename _Allocator::template rebind<_Node>::other
node_allocator_t; _Node_allocator_type;
typedef typename Allocator::template rebind<node*>::other typedef typename _Allocator::template rebind<_Node*>::other
bucket_allocator_t; _Bucket_allocator_type;
node_allocator_t m_node_allocator; _Node_allocator_type _M_node_allocator;
node** m_buckets; _Node** _M_buckets;
size_type m_bucket_count; size_type _M_bucket_count;
size_type m_element_count; size_type _M_element_count;
RehashPolicy m_rehash_policy; _RehashPolicy _M_rehash_policy;
node* _Node*
m_allocate_node(const value_type& v); _M_allocate_node(const value_type& __v);
void void
m_deallocate_node(node* n); _M_deallocate_node(_Node* __n);
void void
m_deallocate_nodes(node**, size_type); _M_deallocate_nodes(_Node**, size_type);
node** _Node**
m_allocate_buckets(size_type n); _M_allocate_buckets(size_type __n);
void void
m_deallocate_buckets(node**, size_type n); _M_deallocate_buckets(_Node**, size_type __n);
public: public:
// Constructor, destructor, assignment, swap // Constructor, destructor, assignment, swap
hashtable(size_type bucket_hint, _Hashtable(size_type __bucket_hint,
const H1&, const H2&, const H&, const _H1&, const _H2&, const _Hash&,
const Equal&, const ExtractKey&, const _Equal&, const _ExtractKey&,
const allocator_type&); const allocator_type&);
template<typename InIter> template<typename _InputIterator>
hashtable(InIter first, InIter last, _Hashtable(_InputIterator __first, _InputIterator __last,
size_type bucket_hint, size_type __bucket_hint,
const H1&, const H2&, const H&, const _H1&, const _H2&, const _Hash&,
const Equal&, const ExtractKey&, const _Equal&, const _ExtractKey&,
const allocator_type&); const allocator_type&);
hashtable(const hashtable&); _Hashtable(const _Hashtable&);
hashtable& _Hashtable&
operator=(const hashtable&); operator=(const _Hashtable&);
~hashtable(); ~_Hashtable();
void swap(hashtable&); void swap(_Hashtable&);
// Basic container operations // Basic container operations
iterator iterator
begin() begin()
{ {
iterator i(m_buckets); iterator __i(_M_buckets);
if (!i.m_cur_node) if (!__i._M_cur_node)
i.m_incr_bucket(); __i._M_incr_bucket();
return i; return __i;
} }
const_iterator const_iterator
begin() const begin() const
{ {
const_iterator i(m_buckets); const_iterator __i(_M_buckets);
if (!i.m_cur_node) if (!__i._M_cur_node)
i.m_incr_bucket(); __i._M_incr_bucket();
return i; return __i;
} }
iterator iterator
end() end()
{ return iterator(m_buckets + m_bucket_count); } { return iterator(_M_buckets + _M_bucket_count); }
const_iterator const_iterator
end() const end() const
{ return const_iterator(m_buckets + m_bucket_count); } { return const_iterator(_M_buckets + _M_bucket_count); }
size_type size_type
size() const size() const
{ return m_element_count; } { return _M_element_count; }
bool bool
empty() const empty() const
...@@ -260,50 +268,50 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -260,50 +268,50 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
allocator_type allocator_type
get_allocator() const get_allocator() const
{ return m_node_allocator; } { return _M_node_allocator; }
size_type size_type
max_size() const max_size() const
{ return m_node_allocator.max_size(); } { return _M_node_allocator.max_size(); }
// Observers // Observers
key_equal key_equal
key_eq() const key_eq() const
{ return this->m_eq; } { return this->_M_eq; }
// hash_function, if present, comes from hash_code_base. // hash_function, if present, comes from _Hash_code_base.
// Bucket operations // Bucket operations
size_type size_type
bucket_count() const bucket_count() const
{ return m_bucket_count; } { return _M_bucket_count; }
size_type size_type
max_bucket_count() const max_bucket_count() const
{ return max_size(); } { return max_size(); }
size_type size_type
bucket_size(size_type n) const bucket_size(size_type __n) const
{ return std::distance(begin(n), end(n)); } { return std::distance(begin(__n), end(__n)); }
size_type size_type
bucket(const key_type& k) const bucket(const key_type& __k) const
{ {
return this->bucket_index(k, this->m_hash_code(k), return this->_M_bucket_index(__k, this->_M_hash_code(__k),
this->m_bucket_count); bucket_count());
} }
local_iterator local_iterator
begin(size_type n) begin(size_type __n)
{ return local_iterator(m_buckets[n]); } { return local_iterator(_M_buckets[__n]); }
local_iterator local_iterator
end(size_type) end(size_type)
{ return local_iterator(0); } { return local_iterator(0); }
const_local_iterator const_local_iterator
begin(size_type n) const begin(size_type __n) const
{ return const_local_iterator(m_buckets[n]); } { return const_local_iterator(_M_buckets[__n]); }
const_local_iterator const_local_iterator
end(size_type) const end(size_type) const
...@@ -315,82 +323,83 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -315,82 +323,83 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
return static_cast<float>(size()) / static_cast<float>(bucket_count()); return static_cast<float>(size()) / static_cast<float>(bucket_count());
} }
// max_load_factor, if present, comes from rehash_base. // max_load_factor, if present, comes from _Rehash_base.
// Generalization of max_load_factor. Extension, not found in TR1. Only // Generalization of max_load_factor. Extension, not found in TR1. Only
// useful if RehashPolicy is something other than the default. // useful if _RehashPolicy is something other than the default.
const RehashPolicy& const _RehashPolicy&
rehash_policy() const __rehash_policy() const
{ return m_rehash_policy; } { return _M_rehash_policy; }
void void
rehash_policy(const RehashPolicy&); __rehash_policy(const _RehashPolicy&);
// Lookup. // Lookup.
iterator iterator
find(const key_type& k); find(const key_type& __k);
const_iterator const_iterator
find(const key_type& k) const; find(const key_type& __k) const;
size_type size_type
count(const key_type& k) const; count(const key_type& __k) const;
std::pair<iterator, iterator> std::pair<iterator, iterator>
equal_range(const key_type& k); equal_range(const key_type& __k);
std::pair<const_iterator, const_iterator> std::pair<const_iterator, const_iterator>
equal_range(const key_type& k) const; equal_range(const key_type& __k) const;
private: // Find, insert and erase helper functions private: // Find, insert and erase helper functions
// ??? This dispatching is a workaround for the fact that we don't // ??? This dispatching is a workaround for the fact that we don't
// have partial specialization of member templates; it would be // have partial specialization of member templates; it would be
// better to just specialize insert on unique_keys. There may be a // better to just specialize insert on __unique_keys. There may be a
// cleaner workaround. // cleaner workaround.
typedef typename __gnu_cxx::__conditional_type<unique_keys, typedef typename __gnu_cxx::__conditional_type<__unique_keys,
std::pair<iterator, bool>, iterator>::__type std::pair<iterator, bool>, iterator>::__type
Insert_Return_Type; _Insert_Return_Type;
typedef typename __gnu_cxx::__conditional_type<unique_keys, typedef typename __gnu_cxx::__conditional_type<__unique_keys,
std::_Select1st<Insert_Return_Type>, std::_Select1st<_Insert_Return_Type>,
std::_Identity<Insert_Return_Type> std::_Identity<_Insert_Return_Type>
>::__type >::__type
Insert_Conv_Type; _Insert_Conv_Type;
node* _Node*
m_find_node(node*, const key_type&, _M_find_node(_Node*, const key_type&,
typename hashtable::hash_code_t) const; typename _Hashtable::_Hash_code_type) const;
iterator iterator
m_insert_bucket(const value_type&, size_type, _M_insert_bucket(const value_type&, size_type,
typename hashtable::hash_code_t); typename _Hashtable::_Hash_code_type);
std::pair<iterator, bool> std::pair<iterator, bool>
m_insert(const value_type&, std::tr1::true_type); _M_insert(const value_type&, std::tr1::true_type);
iterator iterator
m_insert(const value_type&, std::tr1::false_type); _M_insert(const value_type&, std::tr1::false_type);
void void
m_erase_node(node*, node**); _M_erase_node(_Node*, _Node**);
public: public:
// Insert and erase // Insert and erase
Insert_Return_Type _Insert_Return_Type
insert(const value_type& v) insert(const value_type& __v)
{ return m_insert(v, std::tr1::integral_constant<bool, unique_keys>()); } { return _M_insert(__v, std::tr1::integral_constant<bool,
__unique_keys>()); }
iterator iterator
insert(iterator, const value_type& v) insert(iterator, const value_type& __v)
{ return iterator(Insert_Conv_Type()(this->insert(v))); } { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
const_iterator const_iterator
insert(const_iterator, const value_type& v) insert(const_iterator, const value_type& __v)
{ return const_iterator(Insert_Conv_Type()(this->insert(v))); } { return const_iterator(_Insert_Conv_Type()(this->insert(__v))); }
template<typename InIter> template<typename _InputIterator>
void void
insert(InIter first, InIter last); insert(_InputIterator __first, _InputIterator __last);
iterator iterator
erase(iterator); erase(iterator);
...@@ -411,365 +420,407 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -411,365 +420,407 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
clear(); clear();
// Set number of buckets to be appropriate for container of n element. // Set number of buckets to be appropriate for container of n element.
void rehash(size_type n); void rehash(size_type __n);
private: private:
// Unconditionally change size of bucket array to n. // Unconditionally change size of bucket array to n.
void m_rehash(size_type n); void _M_rehash(size_type __n);
}; };
// Definitions of class template hashtable's out-of-line member functions. // Definitions of class template _Hashtable's out-of-line member functions.
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node* typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
m_allocate_node(const value_type& v) __chc, __cit, __uk>::_Node*
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_allocate_node(const value_type& __v)
{ {
node* n = m_node_allocator.allocate(1); _Node* __n = _M_node_allocator.allocate(1);
try try
{ {
get_allocator().construct(&n->m_v, v); get_allocator().construct(&__n->_M_v, __v);
n->m_next = 0; __n->_M_next = 0;
return n; return __n;
} }
catch(...) catch(...)
{ {
m_node_allocator.deallocate(n, 1); _M_node_allocator.deallocate(__n, 1);
__throw_exception_again; __throw_exception_again;
} }
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
m_deallocate_node(node* n) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_deallocate_node(_Node* __n)
{ {
get_allocator().destroy(&n->m_v); get_allocator().destroy(&__n->_M_v);
m_node_allocator.deallocate(n, 1); _M_node_allocator.deallocate(__n, 1);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
m_deallocate_nodes(node** array, size_type n) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_deallocate_nodes(_Node** __array, size_type __n)
{ {
for (size_type i = 0; i < n; ++i) for (size_type __i = 0; __i < __n; ++__i)
{ {
node* p = array[i]; _Node* __p = __array[__i];
while (p) while (__p)
{ {
node* tmp = p; _Node* __tmp = __p;
p = p->m_next; __p = __p->_M_next;
m_deallocate_node(tmp); _M_deallocate_node(__tmp);
} }
array[i] = 0; __array[__i] = 0;
} }
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node** typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
m_allocate_buckets(size_type n) __chc, __cit, __uk>::_Node**
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_allocate_buckets(size_type __n)
{ {
bucket_allocator_t alloc(m_node_allocator); _Bucket_allocator_type __alloc(_M_node_allocator);
// We allocate one extra bucket to hold a sentinel, an arbitrary // We allocate one extra bucket to hold a sentinel, an arbitrary
// non-null pointer. Iterator increment relies on this. // non-null pointer. Iterator increment relies on this.
node** p = alloc.allocate(n + 1); _Node** __p = __alloc.allocate(__n + 1);
std::fill(p, p + n, (node*) 0); std::fill(__p, __p + __n, (_Node*) 0);
p[n] = reinterpret_cast<node*>(0x1000); __p[__n] = reinterpret_cast<_Node*>(0x1000);
return p; return __p;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
m_deallocate_buckets(node** p, size_type n) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_deallocate_buckets(_Node** __p, size_type __n)
{ {
bucket_allocator_t alloc(m_node_allocator); _Bucket_allocator_type __alloc(_M_node_allocator);
alloc.deallocate(p, n + 1); __alloc.deallocate(__p, __n + 1);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable(size_type bucket_hint, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
const H1& h1, const H2& h2, const H& h, _Hashtable(size_type __bucket_hint,
const Eq& eq, const Ex& exk, const _H1& __h1, const _H2& __h2, const _Hash& __h,
const allocator_type& a) const _Equal& __eq, const _ExtractKey& __exk,
: detail::rehash_base<RP, hashtable>(), const allocator_type& __a)
detail::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq, h1, h2, h), : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
detail::map_base<K, V, Ex, u, hashtable>(), __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
m_node_allocator(a), _H1, _H2, _Hash, __chc>(__exk, __eq,
m_bucket_count(0), __h1, __h2, __h),
m_element_count(0), __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
m_rehash_policy() _M_node_allocator(__a),
_M_bucket_count(0),
_M_element_count(0),
_M_rehash_policy()
{ {
m_bucket_count = m_rehash_policy.next_bkt(bucket_hint); _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
m_buckets = m_allocate_buckets(m_bucket_count); _M_buckets = _M_allocate_buckets(_M_bucket_count);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
template<typename InIter> template<typename _InputIterator>
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable(InIter f, InIter l, _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
size_type bucket_hint, _Hashtable(_InputIterator __f, _InputIterator __l,
const H1& h1, const H2& h2, const H& h, size_type __bucket_hint,
const Eq& eq, const Ex& exk, const _H1& __h1, const _H2& __h2, const _Hash& __h,
const allocator_type& a) const _Equal& __eq, const _ExtractKey& __exk,
: detail::rehash_base<RP, hashtable>(), const allocator_type& __a)
detail::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq, : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
h1, h2, h), __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
detail::map_base<K, V, Ex, u, hashtable>(), _H1, _H2, _Hash, __chc>(__exk, __eq,
m_node_allocator(a), __h1, __h2, __h),
m_bucket_count(0), __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
m_element_count(0), _M_node_allocator(__a),
m_rehash_policy() _M_bucket_count(0),
_M_element_count(0),
_M_rehash_policy()
{ {
m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint), _M_bucket_count = std::max(_M_rehash_policy._M_next_bkt(__bucket_hint),
m_rehash_policy. _M_rehash_policy.
bkt_for_elements(detail:: _M_bkt_for_elements(__detail::
distance_fw(f, l))); __distance_fw(__f,
m_buckets = m_allocate_buckets(m_bucket_count); __l)));
_M_buckets = _M_allocate_buckets(_M_bucket_count);
try try
{ {
for (; f != l; ++f) for (; __f != __l; ++__f)
this->insert(*f); this->insert(*__f);
} }
catch(...) catch(...)
{ {
clear(); clear();
m_deallocate_buckets(m_buckets, m_bucket_count); _M_deallocate_buckets(_M_buckets, _M_bucket_count);
__throw_exception_again; __throw_exception_again;
} }
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable(const hashtable& ht) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
: detail::rehash_base<RP, hashtable>(ht), _Hashtable(const _Hashtable& __ht)
detail::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(ht), : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
detail::map_base<K, V, Ex, u, hashtable>(ht), __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
m_node_allocator(ht.get_allocator()), _H1, _H2, _Hash, __chc>(__ht),
m_bucket_count(ht.m_bucket_count), __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
m_element_count(ht.m_element_count), _M_node_allocator(__ht.get_allocator()),
m_rehash_policy(ht.m_rehash_policy) _M_bucket_count(__ht._M_bucket_count),
_M_element_count(__ht._M_element_count),
_M_rehash_policy(__ht._M_rehash_policy)
{ {
m_buckets = m_allocate_buckets(m_bucket_count); _M_buckets = _M_allocate_buckets(_M_bucket_count);
try try
{ {
for (size_type i = 0; i < ht.m_bucket_count; ++i) for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
{ {
node* n = ht.m_buckets[i]; _Node* __n = __ht._M_buckets[__i];
node** tail = m_buckets + i; _Node** __tail = _M_buckets + __i;
while (n) while (__n)
{ {
*tail = m_allocate_node(n->m_v); *__tail = _M_allocate_node(__n->_M_v);
this->copy_code(*tail, n); this->_M_copy_code(*__tail, __n);
tail = &((*tail)->m_next); __tail = &((*__tail)->_M_next);
n = n->m_next; __n = __n->_M_next;
} }
} }
} }
catch(...) catch(...)
{ {
clear(); clear();
m_deallocate_buckets(m_buckets, m_bucket_count); _M_deallocate_buckets(_M_buckets, _M_bucket_count);
__throw_exception_again; __throw_exception_again;
} }
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>& _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>&
operator=(const hashtable& ht) _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
operator=(const _Hashtable& __ht)
{ {
hashtable tmp(ht); _Hashtable __tmp(__ht);
this->swap(tmp); this->swap(__tmp);
return *this; return *this;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
~hashtable() _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
~_Hashtable()
{ {
clear(); clear();
m_deallocate_buckets(m_buckets, m_bucket_count); _M_deallocate_buckets(_M_buckets, _M_bucket_count);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
swap(hashtable& x) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
swap(_Hashtable& __x)
{ {
// The only base class with member variables is hash_code_base. We // The only base class with member variables is hash_code_base. We
// define hash_code_base::m_swap because different specializations // define _Hash_code_base::_M_swap because different specializations
// have different members. // have different members.
detail::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>::m_swap(x); __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
_H1, _H2, _Hash, __chc>::_M_swap(__x);
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 431. Swapping containers with unequal allocators. // 431. Swapping containers with unequal allocators.
std::__alloc_swap<node_allocator_t>::_S_do_it(m_node_allocator, std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator,
x.m_node_allocator); __x._M_node_allocator);
std::swap(m_rehash_policy, x.m_rehash_policy); std::swap(_M_rehash_policy, __x._M_rehash_policy);
std::swap(m_buckets, x.m_buckets); std::swap(_M_buckets, __x._M_buckets);
std::swap(m_bucket_count, x.m_bucket_count); std::swap(_M_bucket_count, __x._M_bucket_count);
std::swap(m_element_count, x.m_element_count); std::swap(_M_element_count, __x._M_element_count);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
rehash_policy(const RP& pol) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
__rehash_policy(const _RehashPolicy& __pol)
{ {
m_rehash_policy = pol; _M_rehash_policy = __pol;
size_type n_bkt = pol.bkt_for_elements(m_element_count); size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
if (n_bkt > m_bucket_count) if (__n_bkt > _M_bucket_count)
m_rehash(n_bkt); _M_rehash(__n_bkt);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
find(const key_type& k) __chc, __cit, __uk>::iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
find(const key_type& __k)
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, this->bucket_count()); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
node* p = m_find_node(m_buckets[n], k, code); _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
return p ? iterator(p, m_buckets + n) : this->end(); return __p ? iterator(__p, _M_buckets + __n) : this->end();
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
find(const key_type& k) const __chc, __cit, __uk>::const_iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
find(const key_type& __k) const
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, this->bucket_count()); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
node* p = m_find_node(m_buckets[n], k, code); _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
return p ? const_iterator(p, m_buckets + n) : this->end(); return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
count(const key_type& k) const __chc, __cit, __uk>::size_type
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
count(const key_type& __k) const
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, this->bucket_count()); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
std::size_t result = 0; std::size_t __result = 0;
for (node* p = m_buckets[n]; p; p = p->m_next) for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
if (this->compare(k, code, p)) if (this->_M_compare(__k, __code, __p))
++result; ++__result;
return result; return __result;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
std::pair<typename hashtable<K, V, A, Ex, Eq, H1, std::pair<typename _Hashtable<_Key, _Value, _Allocator,
H2, H, RP, c, ci, u>::iterator, _ExtractKey, _Equal, _H1,
typename hashtable<K, V, A, Ex, Eq, H1, _H2, _Hash, _RehashPolicy,
H2, H, RP, c, ci, u>::iterator> __chc, __cit, __uk>::iterator,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: typename _Hashtable<_Key, _Value, _Allocator,
equal_range(const key_type& k) _ExtractKey, _Equal, _H1,
_H2, _Hash, _RehashPolicy,
__chc, __cit, __uk>::iterator>
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
equal_range(const key_type& __k)
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, this->bucket_count()); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
node** head = m_buckets + n; _Node** __head = _M_buckets + __n;
node* p = m_find_node(*head, k, code); _Node* __p = _M_find_node(*__head, __k, __code);
if (p) if (__p)
{ {
node* p1 = p->m_next; _Node* __p1 = __p->_M_next;
for (; p1; p1 = p1->m_next) for (; __p1; __p1 = __p1->_M_next)
if (!this->compare(k, code, p1)) if (!this->_M_compare(__k, __code, __p1))
break; break;
iterator first(p, head); iterator __first(__p, __head);
iterator last(p1, head); iterator __last(__p1, __head);
if (!p1) if (!__p1)
last.m_incr_bucket(); __last._M_incr_bucket();
return std::make_pair(first, last); return std::make_pair(__first, __last);
} }
else else
return std::make_pair(this->end(), this->end()); return std::make_pair(this->end(), this->end());
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
std::pair<typename hashtable<K, V, A, Ex, Eq, H1, std::pair<typename _Hashtable<_Key, _Value, _Allocator,
H2, H, RP, c, ci, u>::const_iterator, _ExtractKey, _Equal, _H1,
typename hashtable<K, V, A, Ex, Eq, H1, _H2, _Hash, _RehashPolicy,
H2, H, RP, c, ci, u>::const_iterator> __chc, __cit, __uk>::const_iterator,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: typename _Hashtable<_Key, _Value, _Allocator,
equal_range(const key_type& k) const _ExtractKey, _Equal, _H1,
_H2, _Hash, _RehashPolicy,
__chc, __cit, __uk>::const_iterator>
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
equal_range(const key_type& __k) const
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, this->bucket_count()); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
node** head = m_buckets + n; _Node** __head = _M_buckets + __n;
node* p = m_find_node(*head, k, code); _Node* __p = _M_find_node(*__head, __k, __code);
if (p) if (__p)
{ {
node* p1 = p->m_next; _Node* __p1 = __p->_M_next;
for (; p1; p1 = p1->m_next) for (; __p1; __p1 = __p1->_M_next)
if (!this->compare(k, code, p1)) if (!this->_M_compare(__k, __code, __p1))
break; break;
const_iterator first(p, head); const_iterator __first(__p, __head);
const_iterator last(p1, head); const_iterator __last(__p1, __head);
if (!p1) if (!__p1)
last.m_incr_bucket(); __last._M_incr_bucket();
return std::make_pair(first, last); return std::make_pair(__first, __last);
} }
else else
return std::make_pair(this->end(), this->end()); return std::make_pair(this->end(), this->end());
...@@ -777,295 +828,330 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -777,295 +828,330 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// Find the node whose key compares equal to k, beginning the search // Find the node whose key compares equal to k, beginning the search
// at p (usually the head of a bucket). Return nil if no node is found. // at p (usually the head of a bucket). Return nil if no node is found.
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node* typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Equal, _H1, _H2, _Hash, _RehashPolicy,
m_find_node(node* p, const key_type& k, __chc, __cit, __uk>::_Node*
typename hashtable::hash_code_t code) const _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_find_node(_Node* __p, const key_type& __k,
typename _Hashtable::_Hash_code_type __code) const
{ {
for (; p; p = p->m_next) for (; __p; __p = __p->_M_next)
if (this->compare(k, code, p)) if (this->_M_compare(__k, __code, __p))
return p; return __p;
return false; return false;
} }
// Insert v in bucket n (assumes no element with its key already present). // Insert v in bucket n (assumes no element with its key already present).
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
m_insert_bucket(const value_type& v, size_type n, __chc, __cit, __uk>::iterator
typename hashtable::hash_code_t code) _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_insert_bucket(const value_type& __v, size_type __n,
typename _Hashtable::_Hash_code_type __code)
{ {
std::pair<bool, std::size_t> do_rehash std::pair<bool, std::size_t> __do_rehash
= m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1); = _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
// Allocate the new node before doing the rehash so that we don't // Allocate the new node before doing the rehash so that we don't
// do a rehash if the allocation throws. // do a rehash if the allocation throws.
node* new_node = m_allocate_node(v); _Node* __new_node = _M_allocate_node(__v);
try try
{ {
if (do_rehash.first) if (__do_rehash.first)
{ {
const key_type& k = this->m_extract(v); const key_type& __k = this->_M_extract(__v);
n = this->bucket_index(k, code, do_rehash.second); __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
m_rehash(do_rehash.second); _M_rehash(__do_rehash.second);
} }
new_node->m_next = m_buckets[n]; __new_node->_M_next = _M_buckets[__n];
this->store_code(new_node, code); this->_M_store_code(__new_node, __code);
m_buckets[n] = new_node; _M_buckets[__n] = __new_node;
++m_element_count; ++_M_element_count;
return iterator(new_node, m_buckets + n); return iterator(__new_node, _M_buckets + __n);
} }
catch(...) catch(...)
{ {
m_deallocate_node(new_node); _M_deallocate_node(__new_node);
__throw_exception_again; __throw_exception_again;
} }
} }
// Insert v if no element with its key is already present. // Insert v if no element with its key is already present.
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
std::pair<typename hashtable<K, V, A, Ex, Eq, H1, std::pair<typename _Hashtable<_Key, _Value, _Allocator,
H2, H, RP, c, ci, u>::iterator, bool> _ExtractKey, _Equal, _H1,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H2, _Hash, _RehashPolicy,
m_insert(const value_type& v, std::tr1::true_type) __chc, __cit, __uk>::iterator, bool>
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_insert(const value_type& __v, std::tr1::true_type)
{ {
const key_type& k = this->m_extract(v); const key_type& __k = this->_M_extract(__v);
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
size_type n = this->bucket_index(k, code, m_bucket_count); size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
if (node* p = m_find_node(m_buckets[n], k, code)) if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
return std::make_pair(iterator(p, m_buckets + n), false); return std::make_pair(iterator(__p, _M_buckets + __n), false);
return std::make_pair(m_insert_bucket(v, n, code), true); return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
} }
// Insert v unconditionally. // Insert v unconditionally.
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
m_insert(const value_type& v, std::tr1::false_type) __chc, __cit, __uk>::iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_insert(const value_type& __v, std::tr1::false_type)
{ {
std::pair<bool, std::size_t> do_rehash std::pair<bool, std::size_t> __do_rehash
= m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1); = _M_rehash_policy._M_need_rehash(_M_bucket_count,
if (do_rehash.first) _M_element_count, 1);
m_rehash(do_rehash.second); if (__do_rehash.first)
_M_rehash(__do_rehash.second);
const key_type& k = this->m_extract(v); const key_type& __k = this->_M_extract(__v);
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
size_type n = this->bucket_index(k, code, m_bucket_count); size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
// First find the node, avoid leaking new_node if compare throws. // First find the node, avoid leaking new_node if compare throws.
node* prev = m_find_node(m_buckets[n], k, code); _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
node* new_node = m_allocate_node(v); _Node* __new_node = _M_allocate_node(__v);
if (prev) if (__prev)
{ {
new_node->m_next = prev->m_next; __new_node->_M_next = __prev->_M_next;
prev->m_next = new_node; __prev->_M_next = __new_node;
} }
else else
{ {
new_node->m_next = m_buckets[n]; __new_node->_M_next = _M_buckets[__n];
m_buckets[n] = new_node; _M_buckets[__n] = __new_node;
} }
this->store_code(new_node, code); this->_M_store_code(__new_node, __code);
++m_element_count; ++_M_element_count;
return iterator(new_node, m_buckets + n); return iterator(__new_node, _M_buckets + __n);
} }
// For erase(iterator) and erase(const_iterator). // For erase(iterator) and erase(const_iterator).
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
m_erase_node(node* p, node** b) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_erase_node(_Node* __p, _Node** __b)
{ {
node* cur = *b; _Node* __cur = *__b;
if (cur == p) if (__cur == __p)
*b = cur->m_next; *__b = __cur->_M_next;
else else
{ {
node* next = cur->m_next; _Node* __next = __cur->_M_next;
while (next != p) while (__next != __p)
{ {
cur = next; __cur = __next;
next = cur->m_next; __next = __cur->_M_next;
} }
cur->m_next = next->m_next; __cur->_M_next = __next->_M_next;
} }
m_deallocate_node(p); _M_deallocate_node(__p);
--m_element_count; --_M_element_count;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
template<typename InIter> template<typename _InputIterator>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
insert(InIter first, InIter last) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
insert(_InputIterator __first, _InputIterator __last)
{ {
size_type n_elt = detail::distance_fw(first, last); size_type __n_elt = __detail::__distance_fw(__first, __last);
std::pair<bool, std::size_t> do_rehash std::pair<bool, std::size_t> __do_rehash
= m_rehash_policy.need_rehash(m_bucket_count, m_element_count, n_elt); = _M_rehash_policy._M_need_rehash(_M_bucket_count,
if (do_rehash.first) _M_element_count, __n_elt);
m_rehash(do_rehash.second); if (__do_rehash.first)
_M_rehash(__do_rehash.second);
for (; first != last; ++first)
this->insert(*first); for (; __first != __last; ++__first)
this->insert(*__first);
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
erase(iterator it) __chc, __cit, __uk>::iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(iterator __it)
{ {
iterator result = it; iterator __result = __it;
++result; ++__result;
m_erase_node(it.m_cur_node, it.m_cur_bucket); _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
return result; return __result;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
erase(const_iterator it) __chc, __cit, __uk>::const_iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const_iterator __it)
{ {
const_iterator result = it; const_iterator __result = __it;
++result; ++__result;
m_erase_node(it.m_cur_node, it.m_cur_bucket); _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
return result; return __result;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
erase(const key_type& k) __chc, __cit, __uk>::size_type
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const key_type& __k)
{ {
typename hashtable::hash_code_t code = this->m_hash_code(k); typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
std::size_t n = this->bucket_index(k, code, m_bucket_count); std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
size_type result = 0; size_type __result = 0;
node** slot = m_buckets + n; _Node** __slot = _M_buckets + __n;
while (*slot && !this->compare(k, code, *slot)) while (*__slot && !this->_M_compare(__k, __code, *__slot))
slot = &((*slot)->m_next); __slot = &((*__slot)->_M_next);
while (*slot && this->compare(k, code, *slot)) while (*__slot && this->_M_compare(__k, __code, *__slot))
{ {
node* p = *slot; _Node* __p = *__slot;
*slot = p->m_next; *__slot = __p->_M_next;
m_deallocate_node(p); _M_deallocate_node(__p);
--m_element_count; --_M_element_count;
++result; ++__result;
} }
return result; return __result;
} }
// ??? This could be optimized by taking advantage of the bucket // ??? This could be optimized by taking advantage of the bucket
// structure, but it's not clear that it's worth doing. It probably // structure, but it's not clear that it's worth doing. It probably
// wouldn't even be an optimization unless the load factor is large. // wouldn't even be an optimization unless the load factor is large.
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
erase(iterator first, iterator last) __chc, __cit, __uk>::iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(iterator __first, iterator __last)
{ {
while (first != last) while (__first != __last)
first = this->erase(first); __first = this->erase(__first);
return last; return __last;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _H1, _H2, _Hash, _RehashPolicy,
erase(const_iterator first, const_iterator last) __chc, __cit, __uk>::const_iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
erase(const_iterator __first, const_iterator __last)
{ {
while (first != last) while (__first != __last)
first = this->erase(first); __first = this->erase(__first);
return last; return __last;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
clear() clear()
{ {
m_deallocate_nodes(m_buckets, m_bucket_count); _M_deallocate_nodes(_M_buckets, _M_bucket_count);
m_element_count = 0; _M_element_count = 0;
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
rehash(size_type n) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
rehash(size_type __n)
{ {
m_rehash(std::max(m_rehash_policy.next_bkt(n), _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
m_rehash_policy.bkt_for_elements(m_element_count _M_rehash_policy._M_bkt_for_elements(_M_element_count
+ 1))); + 1)));
} }
template<typename K, typename V, template<typename _Key, typename _Value,
typename A, typename Ex, typename Eq, typename _Allocator, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename RP, typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool c, bool ci, bool u> bool __chc, bool __cit, bool __uk>
void void
hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>:: _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
m_rehash(size_type n) _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_rehash(size_type __n)
{ {
node** new_array = m_allocate_buckets(n); _Node** __new_array = _M_allocate_buckets(__n);
try try
{ {
for (size_type i = 0; i < m_bucket_count; ++i) for (size_type __i = 0; __i < _M_bucket_count; ++__i)
while (node* p = m_buckets[i]) while (_Node* __p = _M_buckets[__i])
{ {
std::size_t new_index = this->bucket_index(p, n); std::size_t __new_index = this->_M_bucket_index(__p, __n);
m_buckets[i] = p->m_next; _M_buckets[__i] = __p->_M_next;
p->m_next = new_array[new_index]; __p->_M_next = __new_array[__new_index];
new_array[new_index] = p; __new_array[__new_index] = __p;
} }
m_deallocate_buckets(m_buckets, m_bucket_count); _M_deallocate_buckets(_M_buckets, _M_bucket_count);
m_bucket_count = n; _M_bucket_count = __n;
m_buckets = new_array; _M_buckets = __new_array;
} }
catch(...) catch(...)
{ {
...@@ -1073,10 +1159,10 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1073,10 +1159,10 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// We can't restore the previous state without calling the hash // We can't restore the previous state without calling the hash
// function again, so the only sensible recovery is to delete // function again, so the only sensible recovery is to delete
// everything. // everything.
m_deallocate_nodes(new_array, n); _M_deallocate_nodes(__new_array, __n);
m_deallocate_buckets(new_array, n); _M_deallocate_buckets(__new_array, __n);
m_deallocate_nodes(m_buckets, m_bucket_count); _M_deallocate_nodes(_M_buckets, _M_bucket_count);
m_element_count = 0; _M_element_count = 0;
__throw_exception_again; __throw_exception_again;
} }
} }
......
...@@ -41,56 +41,58 @@ ...@@ -41,56 +41,58 @@
namespace std namespace std
{ {
_GLIBCXX_BEGIN_NAMESPACE(tr1) _GLIBCXX_BEGIN_NAMESPACE(tr1)
namespace detail namespace __detail
{ {
namespace namespace
{ {
// Helper function: return distance(first, last) for forward // Helper function: return distance(first, last) for forward
// iterators, or 0 for input iterators. // iterators, or 0 for input iterators.
template<class Iterator> template<class _Iterator>
inline typename std::iterator_traits<Iterator>::difference_type inline typename std::iterator_traits<_Iterator>::difference_type
distance_fw(Iterator first, Iterator last, std::input_iterator_tag) __distance_fw(_Iterator __first, _Iterator __last,
std::input_iterator_tag)
{ return 0; } { return 0; }
template<class Iterator> template<class _Iterator>
inline typename std::iterator_traits<Iterator>::difference_type inline typename std::iterator_traits<_Iterator>::difference_type
distance_fw(Iterator first, Iterator last, std::forward_iterator_tag) __distance_fw(_Iterator __first, _Iterator __last,
{ return std::distance(first, last); } std::forward_iterator_tag)
{ return std::distance(__first, __last); }
template<class Iterator> template<class _Iterator>
inline typename std::iterator_traits<Iterator>::difference_type inline typename std::iterator_traits<_Iterator>::difference_type
distance_fw(Iterator first, Iterator last) __distance_fw(_Iterator __first, _Iterator __last)
{ {
typedef typename std::iterator_traits<Iterator>::iterator_category tag; typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
return distance_fw(first, last, tag()); return __distance_fw(__first, __last, _Tag());
} }
// XXX This is a hack. prime_rehash_policy's member functions, and // XXX This is a hack. _Prime_rehash_policy's member functions, and
// certainly the list of primes, should be defined in a .cc file. // certainly the list of primes, should be defined in a .cc file.
// We're temporarily putting them in a header because we don't have a // We're temporarily putting them in a header because we don't have a
// place to put TR1 .cc files yet. There's no good reason for any of // place to put TR1 .cc files yet. There's no good reason for any of
// prime_rehash_policy's member functions to be inline, and there's // _Prime_rehash_policy's member functions to be inline, and there's
// certainly no good reason for X<> to exist at all. // certainly no good reason for _Primes<> to exist at all.
struct lt struct _LessThan
{ {
template<typename X, typename Y> template<typename _Tp, typename _Up>
bool bool
operator()(X x, Y y) operator()(_Tp __x, _Up __y)
{ return x < y; } { return __x < __y; }
}; };
template<int ulongsize = sizeof(unsigned long)> template<int __ulongsize = sizeof(unsigned long)>
struct X struct _Primes
{ {
static const int n_primes = ulongsize != 8 ? 256 : 256 + 48; static const int __n_primes = __ulongsize != 8 ? 256 : 256 + 48;
static const unsigned long primes[256 + 48 + 1]; static const unsigned long __primes[256 + 48 + 1];
}; };
template<int ulongsize> template<int __ulongsize>
const int X<ulongsize>::n_primes; const int _Primes<__ulongsize>::__n_primes;
template<int ulongsize> template<int __ulongsize>
const unsigned long X<ulongsize>::primes[256 + 48 + 1] = const unsigned long _Primes<__ulongsize>::__primes[256 + 48 + 1] =
{ {
2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul, 2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul, 37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
...@@ -135,7 +137,7 @@ namespace ...@@ -135,7 +137,7 @@ namespace
4294967291ul, 4294967291ul,
// Sentinel, so we don't have to test the result of lower_bound, // Sentinel, so we don't have to test the result of lower_bound,
// or, on 64-bit machines, rest of the table. // or, on 64-bit machines, rest of the table.
ulongsize != 8 ? 4294967291ul : (unsigned long)6442450933ull, __ulongsize != 8 ? 4294967291ul : (unsigned long)6442450933ull,
(unsigned long)8589934583ull, (unsigned long)8589934583ull,
(unsigned long)12884901857ull, (unsigned long)17179869143ull, (unsigned long)12884901857ull, (unsigned long)17179869143ull,
(unsigned long)25769803693ull, (unsigned long)34359738337ull, (unsigned long)25769803693ull, (unsigned long)34359738337ull,
...@@ -168,306 +170,315 @@ namespace ...@@ -168,306 +170,315 @@ namespace
}; };
} // anonymous namespace } // anonymous namespace
// Auxiliary types used for all instantiations of hashtable: nodes // Auxiliary types used for all instantiations of _Hashtable: nodes
// and iterators. // and iterators.
// Nodes, used to wrap elements stored in the hash table. A policy // Nodes, used to wrap elements stored in the hash table. A policy
// template parameter of class template hashtable controls whether // template parameter of class template _Hashtable controls whether
// nodes also store a hash code. In some cases (e.g. strings) this // nodes also store a hash code. In some cases (e.g. strings) this
// may be a performance win. // may be a performance win.
template<typename Value, bool cache_hash_code> template<typename _Value, bool __cache_hash_code>
struct hash_node; struct _Hash_node;
template<typename Value> template<typename _Value>
struct hash_node<Value, true> struct _Hash_node<_Value, true>
{ {
Value m_v; _Value _M_v;
std::size_t hash_code; std::size_t _M_hash_code;
hash_node* m_next; _Hash_node* _M_next;
}; };
template<typename Value> template<typename _Value>
struct hash_node<Value, false> struct _Hash_node<_Value, false>
{ {
Value m_v; _Value _M_v;
hash_node* m_next; _Hash_node* _M_next;
}; };
// Local iterators, used to iterate within a bucket but not between // Local iterators, used to iterate within a bucket but not between
// buckets. // buckets.
template<typename Value, bool cache> template<typename _Value, bool __cache>
struct node_iterator_base struct _Node_iterator_base
{ {
node_iterator_base(hash_node<Value, cache>* p) _Node_iterator_base(_Hash_node<_Value, __cache>* __p)
: m_cur(p) { } : _M_cur(__p) { }
void void
incr() _M_incr()
{ m_cur = m_cur->m_next; } { _M_cur = _M_cur->_M_next; }
hash_node<Value, cache>* m_cur; _Hash_node<_Value, __cache>* _M_cur;
}; };
template<typename Value, bool cache> template<typename _Value, bool __cache>
inline bool inline bool
operator==(const node_iterator_base<Value, cache>& x, operator==(const _Node_iterator_base<_Value, __cache>& __x,
const node_iterator_base<Value, cache>& y) const _Node_iterator_base<_Value, __cache>& __y)
{ return x.m_cur == y.m_cur; } { return __x._M_cur == __y._M_cur; }
template<typename Value, bool cache> template<typename _Value, bool __cache>
inline bool inline bool
operator!=(const node_iterator_base<Value, cache>& x, operator!=(const _Node_iterator_base<_Value, __cache>& __x,
const node_iterator_base<Value, cache>& y) const _Node_iterator_base<_Value, __cache>& __y)
{ return x.m_cur != y.m_cur; } { return __x._M_cur != __y._M_cur; }
template<typename Value, bool constant_iterators, bool cache> template<typename _Value, bool __constant_iterators, bool __cache>
struct node_iterator struct _Node_iterator
: public node_iterator_base<Value, cache> : public _Node_iterator_base<_Value, __cache>
{ {
typedef Value value_type; typedef _Value value_type;
typedef typename __gnu_cxx::__conditional_type<constant_iterators, const Value*, Value*>::__type typedef typename
__gnu_cxx::__conditional_type<__constant_iterators,
const _Value*, _Value*>::__type
pointer; pointer;
typedef typename __gnu_cxx::__conditional_type<constant_iterators, const Value&, Value&>::__type typedef typename
__gnu_cxx::__conditional_type<__constant_iterators,
const _Value&, _Value&>::__type
reference; reference;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category; typedef std::forward_iterator_tag iterator_category;
node_iterator() _Node_iterator()
: node_iterator_base<Value, cache>(0) { } : _Node_iterator_base<_Value, __cache>(0) { }
explicit explicit
node_iterator(hash_node<Value, cache>* p) _Node_iterator(_Hash_node<_Value, __cache>* __p)
: node_iterator_base<Value, cache>(p) { } : _Node_iterator_base<_Value, __cache>(__p) { }
reference reference
operator*() const operator*() const
{ return this->m_cur->m_v; } { return this->_M_cur->_M_v; }
pointer pointer
operator->() const operator->() const
{ return &this->m_cur->m_v; } { return &this->_M_cur->_M_v; }
node_iterator& _Node_iterator&
operator++() operator++()
{ {
this->incr(); this->_M_incr();
return *this; return *this;
} }
node_iterator _Node_iterator
operator++(int) operator++(int)
{ {
node_iterator tmp(*this); _Node_iterator __tmp(*this);
this->incr(); this->_M_incr();
return tmp; return __tmp;
} }
}; };
template<typename Value, bool constant_iterators, bool cache> template<typename _Value, bool __constant_iterators, bool __cache>
struct node_const_iterator struct _Node_const_iterator
: public node_iterator_base<Value, cache> : public _Node_iterator_base<_Value, __cache>
{ {
typedef Value value_type; typedef _Value value_type;
typedef const Value* pointer; typedef const _Value* pointer;
typedef const Value& reference; typedef const _Value& reference;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category; typedef std::forward_iterator_tag iterator_category;
node_const_iterator() _Node_const_iterator()
: node_iterator_base<Value, cache>(0) { } : _Node_iterator_base<_Value, __cache>(0) { }
explicit explicit
node_const_iterator(hash_node<Value, cache>* p) _Node_const_iterator(_Hash_node<_Value, __cache>* __p)
: node_iterator_base<Value, cache>(p) { } : _Node_iterator_base<_Value, __cache>(__p) { }
node_const_iterator(const node_iterator<Value, constant_iterators, _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
cache>& x) __cache>& __x)
: node_iterator_base<Value, cache>(x.m_cur) { } : _Node_iterator_base<_Value, __cache>(__x._M_cur) { }
reference reference
operator*() const operator*() const
{ return this->m_cur->m_v; } { return this->_M_cur->_M_v; }
pointer pointer
operator->() const operator->() const
{ return &this->m_cur->m_v; } { return &this->_M_cur->_M_v; }
node_const_iterator& _Node_const_iterator&
operator++() operator++()
{ {
this->incr(); this->_M_incr();
return *this; return *this;
} }
node_const_iterator _Node_const_iterator
operator++(int) operator++(int)
{ {
node_const_iterator tmp(*this); _Node_const_iterator __tmp(*this);
this->incr(); this->_M_incr();
return tmp; return __tmp;
} }
}; };
template<typename Value, bool cache> template<typename _Value, bool __cache>
struct hashtable_iterator_base struct _Hashtable_iterator_base
{ {
hashtable_iterator_base(hash_node<Value, cache>* node, _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node,
hash_node<Value, cache>** bucket) _Hash_node<_Value, __cache>** __bucket)
: m_cur_node(node), m_cur_bucket(bucket) { } : _M_cur_node(__node), _M_cur_bucket(__bucket) { }
void void
incr() _M_incr()
{ {
m_cur_node = m_cur_node->m_next; _M_cur_node = _M_cur_node->_M_next;
if (!m_cur_node) if (!_M_cur_node)
m_incr_bucket(); _M_incr_bucket();
} }
void void
m_incr_bucket(); _M_incr_bucket();
hash_node<Value, cache>* m_cur_node; _Hash_node<_Value, __cache>* _M_cur_node;
hash_node<Value, cache>** m_cur_bucket; _Hash_node<_Value, __cache>** _M_cur_bucket;
}; };
// Global iterators, used for arbitrary iteration within a hash // Global iterators, used for arbitrary iteration within a hash
// table. Larger and more expensive than local iterators. // table. Larger and more expensive than local iterators.
template<typename Value, bool cache> template<typename _Value, bool __cache>
void void
hashtable_iterator_base<Value, cache>:: _Hashtable_iterator_base<_Value, __cache>::
m_incr_bucket() _M_incr_bucket()
{ {
++m_cur_bucket; ++_M_cur_bucket;
// This loop requires the bucket array to have a non-null sentinel. // This loop requires the bucket array to have a non-null sentinel.
while (!*m_cur_bucket) while (!*_M_cur_bucket)
++m_cur_bucket; ++_M_cur_bucket;
m_cur_node = *m_cur_bucket; _M_cur_node = *_M_cur_bucket;
} }
template<typename Value, bool cache> template<typename _Value, bool __cache>
inline bool inline bool
operator==(const hashtable_iterator_base<Value, cache>& x, operator==(const _Hashtable_iterator_base<_Value, __cache>& __x,
const hashtable_iterator_base<Value, cache>& y) const _Hashtable_iterator_base<_Value, __cache>& __y)
{ return x.m_cur_node == y.m_cur_node; } { return __x._M_cur_node == __y._M_cur_node; }
template<typename Value, bool cache> template<typename _Value, bool __cache>
inline bool inline bool
operator!=(const hashtable_iterator_base<Value, cache>& x, operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x,
const hashtable_iterator_base<Value, cache>& y) const _Hashtable_iterator_base<_Value, __cache>& __y)
{ return x.m_cur_node != y.m_cur_node; } { return __x._M_cur_node != __y._M_cur_node; }
template<typename Value, bool constant_iterators, bool cache> template<typename _Value, bool __constant_iterators, bool __cache>
struct hashtable_iterator struct _Hashtable_iterator
: public hashtable_iterator_base<Value, cache> : public _Hashtable_iterator_base<_Value, __cache>
{ {
typedef Value value_type; typedef _Value value_type;
typedef typename __gnu_cxx::__conditional_type<constant_iterators, const Value*, Value*>::__type typedef typename
__gnu_cxx::__conditional_type<__constant_iterators,
const _Value*, _Value*>::__type
pointer; pointer;
typedef typename __gnu_cxx::__conditional_type<constant_iterators, const Value&, Value&>::__type typedef typename
__gnu_cxx::__conditional_type<__constant_iterators,
const _Value&, _Value&>::__type
reference; reference;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category; typedef std::forward_iterator_tag iterator_category;
hashtable_iterator() _Hashtable_iterator()
: hashtable_iterator_base<Value, cache>(0, 0) { } : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
hashtable_iterator(hash_node<Value, cache>* p, _Hashtable_iterator(_Hash_node<_Value, __cache>* __p,
hash_node<Value, cache>** b) _Hash_node<_Value, __cache>** __b)
: hashtable_iterator_base<Value, cache>(p, b) { } : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
explicit explicit
hashtable_iterator(hash_node<Value, cache>** b) _Hashtable_iterator(_Hash_node<_Value, __cache>** __b)
: hashtable_iterator_base<Value, cache>(*b, b) { } : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
reference reference
operator*() const operator*() const
{ return this->m_cur_node->m_v; } { return this->_M_cur_node->_M_v; }
pointer pointer
operator->() const operator->() const
{ return &this->m_cur_node->m_v; } { return &this->_M_cur_node->_M_v; }
hashtable_iterator& _Hashtable_iterator&
operator++() operator++()
{ {
this->incr(); this->_M_incr();
return *this; return *this;
} }
hashtable_iterator _Hashtable_iterator
operator++(int) operator++(int)
{ {
hashtable_iterator tmp(*this); _Hashtable_iterator __tmp(*this);
this->incr(); this->_M_incr();
return tmp; return __tmp;
} }
}; };
template<typename Value, bool constant_iterators, bool cache> template<typename _Value, bool __constant_iterators, bool __cache>
struct hashtable_const_iterator struct _Hashtable_const_iterator
: public hashtable_iterator_base<Value, cache> : public _Hashtable_iterator_base<_Value, __cache>
{ {
typedef Value value_type; typedef _Value value_type;
typedef const Value* pointer; typedef const _Value* pointer;
typedef const Value& reference; typedef const _Value& reference;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category; typedef std::forward_iterator_tag iterator_category;
hashtable_const_iterator() _Hashtable_const_iterator()
: hashtable_iterator_base<Value, cache>(0, 0) { } : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
hashtable_const_iterator(hash_node<Value, cache>* p, _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p,
hash_node<Value, cache>** b) _Hash_node<_Value, __cache>** __b)
: hashtable_iterator_base<Value, cache>(p, b) { } : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
explicit explicit
hashtable_const_iterator(hash_node<Value, cache>** b) _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b)
: hashtable_iterator_base<Value, cache>(*b, b) { } : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
hashtable_const_iterator(const hashtable_iterator<Value, _Hashtable_const_iterator(const _Hashtable_iterator<_Value,
constant_iterators, cache>& x) __constant_iterators, __cache>& __x)
: hashtable_iterator_base<Value, cache>(x.m_cur_node, x.m_cur_bucket) { } : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node,
__x._M_cur_bucket) { }
reference reference
operator*() const operator*() const
{ return this->m_cur_node->m_v; } { return this->_M_cur_node->_M_v; }
pointer pointer
operator->() const operator->() const
{ return &this->m_cur_node->m_v; } { return &this->_M_cur_node->_M_v; }
hashtable_const_iterator& _Hashtable_const_iterator&
operator++() operator++()
{ {
this->incr(); this->_M_incr();
return *this; return *this;
} }
hashtable_const_iterator _Hashtable_const_iterator
operator++(int) operator++(int)
{ {
hashtable_const_iterator tmp(*this); _Hashtable_const_iterator __tmp(*this);
this->incr(); this->_M_incr();
return tmp; return __tmp;
} }
}; };
// Many of class template hashtable's template parameters are policy // Many of class template _Hashtable's template parameters are policy
// classes. These are defaults for the policies. // classes. These are defaults for the policies.
// Default range hashing function: use division to fold a large number // Default range hashing function: use division to fold a large number
// into the range [0, N). // into the range [0, N).
struct mod_range_hashing struct _Mod_range_hashing
{ {
typedef std::size_t first_argument_type; typedef std::size_t first_argument_type;
typedef std::size_t second_argument_type; typedef std::size_t second_argument_type;
typedef std::size_t result_type; typedef std::size_t result_type;
result_type result_type
operator()(first_argument_type r, second_argument_type N) const operator()(first_argument_type __num, second_argument_type __den) const
{ return r % N; } { return __num % __den; }
}; };
// Default ranged hash function H. In principle it should be a // Default ranged hash function H. In principle it should be a
...@@ -475,103 +486,114 @@ namespace ...@@ -475,103 +486,114 @@ namespace
// h(k, N) = h2(h1(k), N), but that would mean making extra copies of // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
// h1 and h2. So instead we'll just use a tag to tell class template // h1 and h2. So instead we'll just use a tag to tell class template
// hashtable to do that composition. // hashtable to do that composition.
struct default_ranged_hash { }; struct _Default_ranged_hash { };
// Default value for rehash policy. Bucket size is (usually) the // Default value for rehash policy. Bucket size is (usually) the
// smallest prime that keeps the load factor small enough. // smallest prime that keeps the load factor small enough.
struct prime_rehash_policy struct _Prime_rehash_policy
{ {
prime_rehash_policy(float z = 1.0); _Prime_rehash_policy(float __z = 1.0);
float float
max_load_factor() const; max_load_factor() const;
// Return a bucket size no smaller than n. // Return a bucket size no smaller than n.
std::size_t std::size_t
next_bkt(std::size_t n) const; _M_next_bkt(std::size_t __n) const;
// Return a bucket count appropriate for n elements // Return a bucket count appropriate for n elements
std::size_t std::size_t
bkt_for_elements(std::size_t n) const; _M_bkt_for_elements(std::size_t __n) const;
// n_bkt is current bucket count, n_elt is current element count, // __n_bkt is current bucket count, __n_elt is current element count,
// and n_ins is number of elements to be inserted. Do we need to // and __n_ins is number of elements to be inserted. Do we need to
// increase bucket count? If so, return make_pair(true, n), where n // increase bucket count? If so, return make_pair(true, n), where n
// is the new bucket count. If not, return make_pair(false, 0). // is the new bucket count. If not, return make_pair(false, 0).
std::pair<bool, std::size_t> std::pair<bool, std::size_t>
need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const; _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
std::size_t __n_ins) const;
float m_max_load_factor; float _M_max_load_factor;
float m_growth_factor; float _M_growth_factor;
mutable std::size_t m_next_resize; mutable std::size_t _M_next_resize;
}; };
inline inline
prime_rehash_policy:: _Prime_rehash_policy::
prime_rehash_policy(float z) _Prime_rehash_policy(float __z)
: m_max_load_factor(z), m_growth_factor(2.f), m_next_resize(0) : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0)
{ } { }
inline float inline float
prime_rehash_policy:: _Prime_rehash_policy::
max_load_factor() const max_load_factor() const
{ return m_max_load_factor; } { return _M_max_load_factor; }
// Return a prime no smaller than n. // Return a prime no smaller than n.
inline std::size_t inline std::size_t
prime_rehash_policy:: _Prime_rehash_policy::
next_bkt(std::size_t n) const _M_next_bkt(std::size_t __n) const
{ {
const unsigned long* const last = X<>::primes + X<>::n_primes; const unsigned long* const __last = (_Primes<>::__primes
const unsigned long* p = std::lower_bound(X<>::primes, last, n); + _Primes<>::__n_primes);
m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor)); const unsigned long* __p = std::lower_bound(_Primes<>::__primes, __last,
return *p; __n);
_M_next_resize = static_cast<std::size_t>(std::ceil(*__p
* _M_max_load_factor));
return *__p;
} }
// Return the smallest prime p such that alpha p >= n, where alpha // Return the smallest prime p such that alpha p >= n, where alpha
// is the load factor. // is the load factor.
inline std::size_t inline std::size_t
prime_rehash_policy:: _Prime_rehash_policy::
bkt_for_elements(std::size_t n) const _M_bkt_for_elements(std::size_t __n) const
{ {
const unsigned long* const last = X<>::primes + X<>::n_primes; const unsigned long* const __last = (_Primes<>::__primes
const float min_bkts = n / m_max_load_factor; + _Primes<>::__n_primes);
const unsigned long* p = std::lower_bound(X<>::primes, last, const float __min_bkts = __n / _M_max_load_factor;
min_bkts, lt()); const unsigned long* __p = std::lower_bound(_Primes<>::__primes, __last,
m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor)); __min_bkts, _LessThan());
return *p; _M_next_resize = static_cast<std::size_t>(std::ceil(*__p
* _M_max_load_factor));
return *__p;
} }
// Finds the smallest prime p such that alpha p > n_elt + n_ins. // Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
// If p > n_bkt, return make_pair(true, p); otherwise return // If p > __n_bkt, return make_pair(true, p); otherwise return
// make_pair(false, 0). In principle this isn't very different from // make_pair(false, 0). In principle this isn't very different from
// bkt_for_elements. // _M_bkt_for_elements.
// The only tricky part is that we're caching the element count at // The only tricky part is that we're caching the element count at
// which we need to rehash, so we don't have to do a floating-point // which we need to rehash, so we don't have to do a floating-point
// multiply for every insertion. // multiply for every insertion.
inline std::pair<bool, std::size_t> inline std::pair<bool, std::size_t>
prime_rehash_policy:: _Prime_rehash_policy::
need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
{ std::size_t __n_ins) const
if (n_elt + n_ins > m_next_resize) {
{ if (__n_elt + __n_ins > _M_next_resize)
float min_bkts = (float(n_ins) + float(n_elt)) / m_max_load_factor; {
if (min_bkts > n_bkt) float __min_bkts = ((float(__n_ins) + float(__n_elt))
{ / _M_max_load_factor);
min_bkts = std::max(min_bkts, m_growth_factor * n_bkt); if (__min_bkts > __n_bkt)
const unsigned long* const last = X<>::primes + X<>::n_primes; {
const unsigned long* p = std::lower_bound(X<>::primes, last, __min_bkts = std::max(__min_bkts, _M_growth_factor * __n_bkt);
min_bkts, lt()); const unsigned long* const __last = (_Primes<>::__primes
m_next_resize = + _Primes<>::__n_primes);
static_cast<std::size_t>(std::ceil(*p * m_max_load_factor)); const unsigned long* __p = std::lower_bound(_Primes<>::__primes,
return std::make_pair(true, *p); __last, __min_bkts,
_LessThan());
_M_next_resize =
static_cast<std::size_t>(std::ceil(*__p * _M_max_load_factor));
return std::make_pair(true, *__p);
} }
else else
{ {
m_next_resize = _M_next_resize =
static_cast<std::size_t>(std::ceil(n_bkt * m_max_load_factor)); static_cast<std::size_t>(std::ceil(__n_bkt
* _M_max_load_factor));
return std::make_pair(false, 0); return std::make_pair(false, 0);
} }
} }
...@@ -579,78 +601,82 @@ namespace ...@@ -579,78 +601,82 @@ namespace
return std::make_pair(false, 0); return std::make_pair(false, 0);
} }
// Base classes for std::tr1::hashtable. We define these base // Base classes for std::tr1::_Hashtable. We define these base
// classes because in some cases we want to do different things // classes because in some cases we want to do different things
// depending on the value of a policy class. In some cases the // depending on the value of a policy class. In some cases the
// policy class affects which member functions and nested typedefs // policy class affects which member functions and nested typedefs
// are defined; we handle that by specializing base class templates. // are defined; we handle that by specializing base class templates.
// Several of the base class templates need to access other members // Several of the base class templates need to access other members
// of class template hashtable, so we use the "curiously recurring // of class template _Hashtable, so we use the "curiously recurring
// template pattern" for them. // template pattern" for them.
// class template map_base. If the hashtable has a value type of the // class template _Map_base. If the hashtable has a value type of the
// form pair<T1, T2> and a key extraction policy that returns the // form pair<T1, T2> and a key extraction policy that returns the
// first part of the pair, the hashtable gets a mapped_type typedef. // first part of the pair, the hashtable gets a mapped_type typedef.
// If it satisfies those criteria and also has unique keys, then it // If it satisfies those criteria and also has unique keys, then it
// also gets an operator[]. // also gets an operator[].
template<typename K, typename V, typename Ex, bool unique, typename Hashtable> template<typename _Key, typename _Value, typename _Ex, bool __unique,
struct map_base { }; typename _Hashtable>
struct _Map_base { };
template<typename K, typename Pair, typename Hashtable> template<typename _Key, typename _Pair, typename _Hashtable>
struct map_base<K, Pair, std::_Select1st<Pair>, false, Hashtable> struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
{ {
typedef typename Pair::second_type mapped_type; typedef typename _Pair::second_type mapped_type;
}; };
template<typename K, typename Pair, typename Hashtable> template<typename _Key, typename _Pair, typename _Hashtable>
struct map_base<K, Pair, std::_Select1st<Pair>, true, Hashtable> struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
{ {
typedef typename Pair::second_type mapped_type; typedef typename _Pair::second_type mapped_type;
mapped_type& mapped_type&
operator[](const K& k); operator[](const _Key& __k);
}; };
template<typename K, typename Pair, typename Hashtable> template<typename _Key, typename _Pair, typename _Hashtable>
typename map_base<K, Pair, std::_Select1st<Pair>, true, Hashtable>::mapped_type& typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
map_base<K, Pair, std::_Select1st<Pair>, true, Hashtable>:: true, _Hashtable>::mapped_type&
operator[](const K& k) _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
{ operator[](const _Key& __k)
Hashtable* h = static_cast<Hashtable*>(this); {
typename Hashtable::hash_code_t code = h->m_hash_code(k); _Hashtable* __h = static_cast<_Hashtable*>(this);
std::size_t n = h->bucket_index(k, code, h->bucket_count()); typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
std::size_t __n = __h->_M_bucket_index(__k, __code,
typename Hashtable::node* p = h->m_find_node(h->m_buckets[n], k, code); __h->_M_bucket_count);
if (!p)
return h->m_insert_bucket(std::make_pair(k, mapped_type()), typename _Hashtable::_Node* __p =
n, code)->second; __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
return (p->m_v).second; if (!__p)
return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
__n, __code)->second;
return (__p->_M_v).second;
} }
// class template rehash_base. Give hashtable the max_load_factor // class template _Rehash_base. Give hashtable the max_load_factor
// functions iff the rehash policy is prime_rehash_policy. // functions iff the rehash policy is _Prime_rehash_policy.
template<typename RehashPolicy, typename Hashtable> template<typename _RehashPolicy, typename _Hashtable>
struct rehash_base { }; struct _Rehash_base { };
template<typename Hashtable> template<typename _Hashtable>
struct rehash_base<prime_rehash_policy, Hashtable> struct _Rehash_base<_Prime_rehash_policy, _Hashtable>
{ {
float float
max_load_factor() const max_load_factor() const
{ {
const Hashtable* This = static_cast<const Hashtable*>(this); const _Hashtable* __this = static_cast<const _Hashtable*>(this);
return This->rehash_policy().max_load_factor(); return __this->__rehash_policy().max_load_factor();
} }
void void
max_load_factor(float z) max_load_factor(float __z)
{ {
Hashtable* This = static_cast<Hashtable*>(this); _Hashtable* __this = static_cast<_Hashtable*>(this);
This->rehash_policy(prime_rehash_policy(z)); __this->__rehash_policy(_Prime_rehash_policy(__z));
} }
}; };
// Class template hash_code_base. Encapsulates two policy issues that // Class template _Hash_code_base. Encapsulates two policy issues that
// aren't quite orthogonal. // aren't quite orthogonal.
// (1) the difference between using a ranged hash function and using // (1) the difference between using a ranged hash function and using
// the combination of a hash function and a range-hashing function. // the combination of a hash function and a range-hashing function.
...@@ -662,62 +688,67 @@ namespace ...@@ -662,62 +688,67 @@ namespace
// objects here, for convenience. // objects here, for convenience.
// Primary template: unused except as a hook for specializations. // Primary template: unused except as a hook for specializations.
template<typename Key, typename Value, template<typename _Key, typename _Value,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H, typename _H1, typename _H2, typename _Hash,
bool cache_hash_code> bool __cache_hash_code>
struct hash_code_base; struct _Hash_code_base;
// Specialization: ranged hash function, no caching hash codes. H1 // Specialization: ranged hash function, no caching hash codes. H1
// and H2 are provided but ignored. We define a dummy hash code type. // and H2 are provided but ignored. We define a dummy hash code type.
template<typename Key, typename Value, template<typename _Key, typename _Value,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H> typename _H1, typename _H2, typename _Hash>
struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, false> struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
_Hash, false>
{ {
protected: protected:
hash_code_base(const ExtractKey& ex, const Equal& eq, _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
const H1&, const H2&, const H& h) const _H1&, const _H2&, const _Hash& __h)
: m_extract(ex), m_eq(eq), m_ranged_hash(h) { } : _M_extract(__ex), _M_eq(__eq), _M_ranged_hash(__h) { }
typedef void* hash_code_t; typedef void* _Hash_code_type;
hash_code_t _Hash_code_type
m_hash_code(const Key& k) const _M_hash_code(const _Key& __key) const
{ return 0; } { return 0; }
std::size_t std::size_t
bucket_index(const Key& k, hash_code_t, std::size_t N) const _M_bucket_index(const _Key& __k, _Hash_code_type,
{ return m_ranged_hash(k, N); } std::size_t __n) const
{ return _M_ranged_hash(__k, __n); }
std::size_t std::size_t
bucket_index(const hash_node<Value, false>* p, std::size_t N) const _M_bucket_index(const _Hash_node<_Value, false>* __p,
{ return m_ranged_hash(m_extract(p->m_v), N); } std::size_t __n) const
{ return _M_ranged_hash(_M_extract(__p->_M_v), __n); }
bool bool
compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const _M_compare(const _Key& __k, _Hash_code_type,
{ return m_eq(k, m_extract(n->m_v)); } _Hash_node<_Value, false>* __n) const
{ return _M_eq(__k, _M_extract(__n->_M_v)); }
void void
store_code(hash_node<Value, false>*, hash_code_t) const _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
{ } { }
void void
copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const _M_copy_code(_Hash_node<_Value, false>*,
const _Hash_node<_Value, false>*) const
{ } { }
void void
m_swap(hash_code_base& x) _M_swap(_Hash_code_base& __x)
{ {
std::swap(m_extract, x.m_extract); std::swap(_M_extract, __x._M_extract);
std::swap(m_eq, x.m_eq); std::swap(_M_eq, __x._M_eq);
std::swap(m_ranged_hash, x.m_ranged_hash); std::swap(_M_ranged_hash, __x._M_ranged_hash);
} }
protected: protected:
ExtractKey m_extract; _ExtractKey _M_extract;
Equal m_eq; _Equal _M_eq;
H m_ranged_hash; _Hash _M_ranged_hash;
}; };
...@@ -728,137 +759,146 @@ namespace ...@@ -728,137 +759,146 @@ namespace
// Specialization: ranged hash function, cache hash codes. This // Specialization: ranged hash function, cache hash codes. This
// combination is meaningless, so we provide only a declaration // combination is meaningless, so we provide only a declaration
// and no definition. // and no definition.
template<typename Key, typename Value, template<typename _Key, typename _Value,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2, typename H> typename _H1, typename _H2, typename _Hash>
struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, true>; struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
_Hash, true>;
// Specialization: hash function and range-hashing function, no // Specialization: hash function and range-hashing function, no
// caching of hash codes. H is provided but ignored. Provides // caching of hash codes. H is provided but ignored. Provides
// typedef and accessor required by TR1. // typedef and accessor required by TR1.
template<typename Key, typename Value, template<typename _Key, typename _Value,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2> typename _H1, typename _H2>
struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
default_ranged_hash, false> _Default_ranged_hash, false>
{ {
typedef H1 hasher; typedef _H1 hasher;
hasher hasher
hash_function() const hash_function() const
{ return m_h1; } { return _M_h1; }
protected: protected:
hash_code_base(const ExtractKey& ex, const Equal& eq, _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
const H1& h1, const H2& h2, const default_ranged_hash&) const _H1& __h1, const _H2& __h2,
: m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { } const _Default_ranged_hash&)
: _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
typedef std::size_t hash_code_t; typedef std::size_t _Hash_code_type;
hash_code_t _Hash_code_type
m_hash_code(const Key& k) const _M_hash_code(const _Key& __k) const
{ return m_h1(k); } { return _M_h1(__k); }
std::size_t std::size_t
bucket_index(const Key&, hash_code_t c, std::size_t N) const _M_bucket_index(const _Key&, _Hash_code_type __c,
{ return m_h2(c, N); } std::size_t __n) const
{ return _M_h2(__c, __n); }
std::size_t std::size_t
bucket_index(const hash_node<Value, false>* p, std::size_t N) const _M_bucket_index(const _Hash_node<_Value, false>* __p,
{ return m_h2(m_h1(m_extract(p->m_v)), N); } std::size_t __n) const
{ return _M_h2(_M_h1(_M_extract(__p->_M_v)), __n); }
bool bool
compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const _M_compare(const _Key& __k, _Hash_code_type,
{ return m_eq(k, m_extract(n->m_v)); } _Hash_node<_Value, false>* __n) const
{ return _M_eq(__k, _M_extract(__n->_M_v)); }
void void
store_code(hash_node<Value, false>*, hash_code_t) const _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
{ } { }
void void
copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const _M_copy_code(_Hash_node<_Value, false>*,
const _Hash_node<_Value, false>*) const
{ } { }
void void
m_swap(hash_code_base& x) _M_swap(_Hash_code_base& __x)
{ {
std::swap(m_extract, x.m_extract); std::swap(_M_extract, __x._M_extract);
std::swap(m_eq, x.m_eq); std::swap(_M_eq, __x._M_eq);
std::swap(m_h1, x.m_h1); std::swap(_M_h1, __x._M_h1);
std::swap(m_h2, x.m_h2); std::swap(_M_h2, __x._M_h2);
} }
protected: protected:
ExtractKey m_extract; _ExtractKey _M_extract;
Equal m_eq; _Equal _M_eq;
H1 m_h1; _H1 _M_h1;
H2 m_h2; _H2 _M_h2;
}; };
// Specialization: hash function and range-hashing function, // Specialization: hash function and range-hashing function,
// caching hash codes. H is provided but ignored. Provides // caching hash codes. H is provided but ignored. Provides
// typedef and accessor required by TR1. // typedef and accessor required by TR1.
template<typename Key, typename Value, template<typename _Key, typename _Value,
typename ExtractKey, typename Equal, typename _ExtractKey, typename _Equal,
typename H1, typename H2> typename _H1, typename _H2>
struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
default_ranged_hash, true> _Default_ranged_hash, true>
{ {
typedef H1 hasher; typedef _H1 hasher;
hasher hasher
hash_function() const hash_function() const
{ return m_h1; } { return _M_h1; }
protected: protected:
hash_code_base(const ExtractKey& ex, const Equal& eq, _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
const H1& h1, const H2& h2, const default_ranged_hash&) const _H1& __h1, const _H2& __h2,
: m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { } const _Default_ranged_hash&)
: _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
typedef std::size_t hash_code_t; typedef std::size_t _Hash_code_type;
hash_code_t _Hash_code_type
m_hash_code(const Key& k) const _M_hash_code(const _Key& __k) const
{ return m_h1(k); } { return _M_h1(__k); }
std::size_t std::size_t
bucket_index(const Key&, hash_code_t c, std::size_t N) const _M_bucket_index(const _Key&, _Hash_code_type __c,
{ return m_h2(c, N); } std::size_t __n) const
{ return _M_h2(__c, __n); }
std::size_t std::size_t
bucket_index(const hash_node<Value, true>* p, std::size_t N) const _M_bucket_index(const _Hash_node<_Value, true>* __p,
{ return m_h2(p->hash_code, N); } std::size_t __n) const
{ return _M_h2(__p->_M_hash_code, __n); }
bool bool
compare(const Key& k, hash_code_t c, hash_node<Value, true>* n) const _M_compare(const _Key& __k, _Hash_code_type __c,
{ return c == n->hash_code && m_eq(k, m_extract(n->m_v)); } _Hash_node<_Value, true>* __n) const
{ return __c == __n->_M_hash_code && _M_eq(__k, _M_extract(__n->_M_v)); }
void void
store_code(hash_node<Value, true>* n, hash_code_t c) const _M_store_code(_Hash_node<_Value, true>* __n, _Hash_code_type __c) const
{ n->hash_code = c; } { __n->_M_hash_code = __c; }
void void
copy_code(hash_node<Value, true>* to, _M_copy_code(_Hash_node<_Value, true>* __to,
const hash_node<Value, true>* from) const const _Hash_node<_Value, true>* __from) const
{ to->hash_code = from->hash_code; } { __to->_M_hash_code = __from->_M_hash_code; }
void void
m_swap(hash_code_base& x) _M_swap(_Hash_code_base& __x)
{ {
std::swap(m_extract, x.m_extract); std::swap(_M_extract, __x._M_extract);
std::swap(m_eq, x.m_eq); std::swap(_M_eq, __x._M_eq);
std::swap(m_h1, x.m_h1); std::swap(_M_h1, __x._M_h1);
std::swap(m_h2, x.m_h2); std::swap(_M_h2, __x._M_h2);
} }
protected: protected:
ExtractKey m_extract; _ExtractKey _M_extract;
Equal m_eq; _Equal _M_eq;
H1 m_h1; _H1 _M_h1;
H2 m_h2; _H2 _M_h2;
}; };
} // namespace detail } // namespace __detail
_GLIBCXX_END_NAMESPACE _GLIBCXX_END_NAMESPACE
} // namespace std::tr1 } // namespace std::tr1
......
...@@ -43,120 +43,124 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -43,120 +43,124 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// XXX When we get typedef templates these class definitions // XXX When we get typedef templates these class definitions
// will be unnecessary. // will be unnecessary.
template<class Key, class T, template<class _Key, class _Tp,
class Hash = hash<Key>, class _Hash = hash<_Key>,
class Pred = std::equal_to<Key>, class _Pred = std::equal_to<_Key>,
class Alloc = std::allocator<std::pair<const Key, T> >, class _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
bool cache_hash_code = false> bool __cache_hash_code = false>
class unordered_map class unordered_map
: public hashtable<Key, std::pair<const Key, T>, Alloc, : public _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc,
std::_Select1st<std::pair<const Key, T> >, Pred, std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, false, true> __cache_hash_code, false, true>
{ {
typedef hashtable<Key, std::pair<const Key, T>, Alloc, typedef _Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc,
std::_Select1st<std::pair<const Key, T> >, Pred, std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, false, true> __cache_hash_code, false, true>
Base; _Base;
public: public:
typedef typename Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename Base::hasher hasher; typedef typename _Base::hasher hasher;
typedef typename Base::key_equal key_equal; typedef typename _Base::key_equal key_equal;
typedef typename Base::allocator_type allocator_type; typedef typename _Base::allocator_type allocator_type;
explicit explicit
unordered_map(size_type n = 10, unordered_map(size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base(n, hf, detail::mod_range_hashing(), : _Base(__n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), __detail::_Default_ranged_hash(),
eql, std::_Select1st<std::pair<const Key, T> >(), a) __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
{ } { }
template<typename InputIterator> template<typename _InputIterator>
unordered_map(InputIterator f, InputIterator l, unordered_map(_InputIterator __f, _InputIterator __l,
size_type n = 10, size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base (f, l, n, hf, detail::mod_range_hashing(), : _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), __detail::_Default_ranged_hash(),
eql, std::_Select1st<std::pair<const Key, T> >(), a) __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
{ } { }
}; };
template<class Key, class T, template<class _Key, class _Tp,
class Hash = hash<Key>, class _Hash = hash<_Key>,
class Pred = std::equal_to<Key>, class _Pred = std::equal_to<_Key>,
class Alloc = std::allocator<std::pair<const Key, T> >, class _Alloc = std::allocator<std::pair<const _Key, _Tp> >,
bool cache_hash_code = false> bool __cache_hash_code = false>
class unordered_multimap class unordered_multimap
: public hashtable <Key, std::pair<const Key, T>, : public _Hashtable<_Key, std::pair<const _Key, _Tp>,
Alloc, _Alloc,
std::_Select1st<std::pair<const Key, T> >, Pred, std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, false, false> __cache_hash_code, false, false>
{ {
typedef hashtable <Key, std::pair<const Key, T>, typedef _Hashtable<_Key, std::pair<const _Key, _Tp>,
Alloc, _Alloc,
std::_Select1st<std::pair<const Key, T> >, Pred, std::_Select1st<std::pair<const _Key, _Tp> >, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, false, false> __cache_hash_code, false, false>
Base; _Base;
public: public:
typedef typename Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename Base::hasher hasher; typedef typename _Base::hasher hasher;
typedef typename Base::key_equal key_equal; typedef typename _Base::key_equal key_equal;
typedef typename Base::allocator_type allocator_type; typedef typename _Base::allocator_type allocator_type;
explicit explicit
unordered_multimap(size_type n = 10, unordered_multimap(size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base (n, hf, detail::mod_range_hashing(), : _Base(__n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), __detail::_Default_ranged_hash(),
eql, std::_Select1st<std::pair<const Key, T> >(), a) __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
{ } { }
template<typename InputIterator> template<typename _InputIterator>
unordered_multimap(InputIterator f, InputIterator l, unordered_multimap(_InputIterator __f, _InputIterator __l,
typename Base::size_type n = 0, typename _Base::size_type __n = 0,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base (f, l, n, hf, detail::mod_range_hashing(), : _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), __detail::_Default_ranged_hash(),
eql, std::_Select1st<std::pair<const Key, T> >(), a) __eql, std::_Select1st<std::pair<const _Key, _Tp> >(), __a)
{ } { }
}; };
template<class Key, class T, class Hash, class Pred, class Alloc, template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc,
bool cache_hash_code> bool __cache_hash_code>
inline void inline void
swap(unordered_map<Key, T, Hash, Pred, Alloc, cache_hash_code>& x, swap(unordered_map<_Key, _Tp, _Hash, _Pred,
unordered_map<Key, T, Hash, Pred, Alloc, cache_hash_code>& y) _Alloc, __cache_hash_code>& __x,
{ x.swap(y); } unordered_map<_Key, _Tp, _Hash, _Pred,
_Alloc, __cache_hash_code>& __y)
template<class Key, class T, class Hash, class Pred, class Alloc, { __x.swap(__y); }
bool cache_hash_code>
template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc,
bool __cache_hash_code>
inline void inline void
swap(unordered_multimap<Key, T, Hash, Pred, Alloc, cache_hash_code>& x, swap(unordered_multimap<_Key, _Tp, _Hash, _Pred,
unordered_multimap<Key, T, Hash, Pred, Alloc, cache_hash_code>& y) _Alloc, __cache_hash_code>& __x,
{ x.swap(y); } unordered_multimap<_Key, _Tp, _Hash, _Pred,
_Alloc, __cache_hash_code>& __y)
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE _GLIBCXX_END_NAMESPACE
} }
......
...@@ -43,114 +43,122 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -43,114 +43,122 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// XXX When we get typedef templates these class definitions // XXX When we get typedef templates these class definitions
// will be unnecessary. // will be unnecessary.
template<class Value, template<class _Value,
class Hash = hash<Value>, class _Hash = hash<_Value>,
class Pred = std::equal_to<Value>, class _Pred = std::equal_to<_Value>,
class Alloc = std::allocator<Value>, class _Alloc = std::allocator<_Value>,
bool cache_hash_code = false> bool __cache_hash_code = false>
class unordered_set class unordered_set
: public hashtable<Value, Value, Alloc, : public _Hashtable<_Value, _Value, _Alloc,
std::_Identity<Value>, Pred, std::_Identity<_Value>, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, true, true> __cache_hash_code, true, true>
{ {
typedef hashtable<Value, Value, Alloc, typedef _Hashtable<_Value, _Value, _Alloc,
std::_Identity<Value>, Pred, std::_Identity<_Value>, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, true, true> __cache_hash_code, true, true>
Base; _Base;
public: public:
typedef typename Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename Base::hasher hasher; typedef typename _Base::hasher hasher;
typedef typename Base::key_equal key_equal; typedef typename _Base::key_equal key_equal;
typedef typename Base::allocator_type allocator_type; typedef typename _Base::allocator_type allocator_type;
explicit explicit
unordered_set(size_type n = 10, unordered_set(size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base(n, hf, detail::mod_range_hashing(), : _Base(__n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), eql, std::_Identity<Value>(), a) __detail::_Default_ranged_hash(), __eql,
std::_Identity<_Value>(), __a)
{ } { }
template<typename InputIterator> template<typename _InputIterator>
unordered_set(InputIterator f, InputIterator l, unordered_set(_InputIterator __f, _InputIterator __l,
size_type n = 10, size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base(f, l, n, hf, detail::mod_range_hashing(), : _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), eql, std::_Identity<Value>(), a) __detail::_Default_ranged_hash(), __eql,
std::_Identity<_Value>(), __a)
{ } { }
}; };
template<class Value, template<class _Value,
class Hash = hash<Value>, class _Hash = hash<_Value>,
class Pred = std::equal_to<Value>, class _Pred = std::equal_to<_Value>,
class Alloc = std::allocator<Value>, class _Alloc = std::allocator<_Value>,
bool cache_hash_code = false> bool __cache_hash_code = false>
class unordered_multiset class unordered_multiset
: public hashtable <Value, Value, Alloc, : public _Hashtable<_Value, _Value, _Alloc,
std::_Identity<Value>, Pred, std::_Identity<_Value>, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, true, false> __cache_hash_code, true, false>
{ {
typedef hashtable<Value, Value, Alloc, typedef _Hashtable<_Value, _Value, _Alloc,
std::_Identity<Value>, Pred, std::_Identity<_Value>, _Pred,
Hash, detail::mod_range_hashing, _Hash, __detail::_Mod_range_hashing,
detail::default_ranged_hash, __detail::_Default_ranged_hash,
detail::prime_rehash_policy, __detail::_Prime_rehash_policy,
cache_hash_code, true, false> __cache_hash_code, true, false>
Base; _Base;
public: public:
typedef typename Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename Base::hasher hasher; typedef typename _Base::hasher hasher;
typedef typename Base::key_equal key_equal; typedef typename _Base::key_equal key_equal;
typedef typename Base::allocator_type allocator_type; typedef typename _Base::allocator_type allocator_type;
explicit explicit
unordered_multiset(size_type n = 10, unordered_multiset(size_type __n = 10,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base(n, hf, detail::mod_range_hashing(), : _Base(__n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), eql, std::_Identity<Value>(), a) __detail::_Default_ranged_hash(), __eql,
std::_Identity<_Value>(), __a)
{ } { }
template<typename InputIterator> template<typename _InputIterator>
unordered_multiset(InputIterator f, InputIterator l, unordered_multiset(_InputIterator __f, _InputIterator __l,
typename Base::size_type n = 0, typename _Base::size_type __n = 0,
const hasher& hf = hasher(), const hasher& __hf = hasher(),
const key_equal& eql = key_equal(), const key_equal& __eql = key_equal(),
const allocator_type& a = allocator_type()) const allocator_type& __a = allocator_type())
: Base(f, l, n, hf, detail::mod_range_hashing(), : _Base(__f, __l, __n, __hf, __detail::_Mod_range_hashing(),
detail::default_ranged_hash(), eql, std::_Identity<Value>(), a) __detail::_Default_ranged_hash(), __eql,
std::_Identity<_Value>(), __a)
{ } { }
}; };
template<class Value, class Hash, class Pred, class Alloc, template<class _Value, class _Hash, class _Pred, class _Alloc,
bool cache_hash_code> bool __cache_hash_code>
inline void inline void
swap (unordered_set<Value, Hash, Pred, Alloc, cache_hash_code>& x, swap (unordered_set<_Value, _Hash, _Pred,
unordered_set<Value, Hash, Pred, Alloc, cache_hash_code>& y) _Alloc, __cache_hash_code>& __x,
{ x.swap(y); } unordered_set<_Value, _Hash, _Pred,
_Alloc, __cache_hash_code>& __y)
template<class Value, class Hash, class Pred, class Alloc, { __x.swap(__y); }
bool cache_hash_code>
template<class _Value, class _Hash, class _Pred, class _Alloc,
bool __cache_hash_code>
inline void inline void
swap(unordered_multiset<Value, Hash, Pred, Alloc, cache_hash_code>& x, swap(unordered_multiset<_Value, _Hash, _Pred,
unordered_multiset<Value, Hash, Pred, Alloc, cache_hash_code>& y) _Alloc, __cache_hash_code>& __x,
{ x.swap(y); } unordered_multiset<_Value, _Hash, _Pred,
_Alloc, __cache_hash_code>& __y)
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE _GLIBCXX_END_NAMESPACE
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment