diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
index c047fa6711..a43e84be8e 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
@@ -478,6 +478,12 @@
true
true
+
+ true
+ true
+ true
+ true
+
true
true
diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
index 5973783fcd..ba2e38a656 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -1465,6 +1465,9 @@
beast_core\containers
+
+ beast_core\containers
+
diff --git a/Subtrees/beast/modules/beast_core/beast_core.cpp b/Subtrees/beast/modules/beast_core/beast_core.cpp
index 82944cfda2..aae18a2485 100644
--- a/Subtrees/beast/modules/beast_core/beast_core.cpp
+++ b/Subtrees/beast/modules/beast_core/beast_core.cpp
@@ -145,6 +145,7 @@ namespace beast
#include "containers/beast_Variant.cpp"
#include "containers/DynamicArray.cpp"
#include "containers/DynamicList.cpp"
+#include "containers/HashMap.cpp"
#include "diagnostic/beast_Debug.cpp"
#include "diagnostic/beast_Error.cpp"
diff --git a/Subtrees/beast/modules/beast_core/containers/HashMap.cpp b/Subtrees/beast/modules/beast_core/containers/HashMap.cpp
new file mode 100644
index 0000000000..b4e4b629be
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/HashMap.cpp
@@ -0,0 +1,149 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+class HashMapTests : public UnitTest
+{
+public:
+ enum
+ {
+ numberOfItems = 100 * 1000
+ };
+
+ template
+ class TestTraits
+ {
+ public:
+ struct Value
+ {
+ int unused;
+ };
+
+ struct Key
+ {
+ class Equal
+ {
+ public:
+ bool operator() (Key const& lhs, Key const& rhs) const noexcept
+ {
+ return memcmp (lhs.data, rhs.data, keyBytes) == 0;
+ }
+ };
+
+ // stateful hardened hash
+ class Hash
+ {
+ public:
+ explicit Hash (HashValue seedToUse = Random::getSystemRandom ().nextInt ())
+ : m_seed (seedToUse)
+ {
+ }
+
+ HashValue generateHash (Key const& key) const noexcept
+ {
+ HashValue hash;
+ Murmur::Hash (key.data, keyBytes, m_seed, &hash);
+ return hash;
+ }
+
+ private:
+ HashValue m_seed;
+ };
+
+ /*
+ Key ()
+ : std::memset (data, 0, keyBytes)
+ {
+ }
+ */
+
+ uint8 data [keyBytes];
+ };
+
+ typedef Key key_type;
+ typedef Value value_type;
+ typedef typename Key::Hash hasher;
+ typedef typename Key::Equal key_equal;
+ typedef std::size_t size_type;
+
+ TestTraits (size_type const numberOfKeys, Random& random)
+ {
+ // need to static_bassert keyBytes can represent numberOfKeys. Log base 256 or something?
+
+ m_keys.reserve (numberOfKeys);
+ m_shuffled_keys.reserve (numberOfKeys);
+ for (size_type i = 0; i < numberOfKeys; ++i)
+ {
+ // VFALCO NOTE std::vector is garbage..want to emplace_back() here
+ Key key;
+ memset (key.data, 0, sizeof (key.data));
+ memcpy (& key.data [0], &i, std::min (sizeof (key.data), sizeof (i)));
+ m_keys.push_back (key);
+ m_shuffled_keys.push_back (&m_keys [i]);
+ }
+
+ UnitTestUtilities::repeatableShuffle (numberOfKeys, m_shuffled_keys, random);
+ }
+
+ Key const& getKey (size_type index) const noexcept
+ {
+ return *m_shuffled_keys [index];
+ }
+
+ private:
+ std::vector m_keys;
+ std::vector m_shuffled_keys;
+ };
+
+ template
+ void testInsert (std::size_t numberOfKeys, Random& random)
+ {
+ beginTestCase (String
+ ("insertion, numberOfKeys = ") + String::fromNumber (numberOfKeys) +
+ ", keyBytes = " + String::fromNumber (keyBytes));
+
+ typedef TestTraits Traits;
+ Traits traits (numberOfKeys, random);
+
+ typedef HashMap <
+ typename Traits::key_type,
+ typename Traits::value_type,
+ typename Traits::hasher,
+ typename Traits::key_equal> Map;
+ Map map;
+
+ for (std::size_t i = 0; i < numberOfKeys; ++i)
+ map.insert (traits.getKey (i));
+
+ this->logMessage ("load_factor = " + String::fromNumber (map.load_factor ()));
+ }
+
+ void runTest ()
+ {
+ int64 const seedValue = 072472;
+ Random random (seedValue);
+ testInsert <4> (numberOfItems, random);
+ testInsert <20> (numberOfItems, random);
+ }
+
+ HashMapTests () : UnitTest ("HashMap", "beast")
+ {
+ }
+};
+
+static HashMapTests hashMapTests;
diff --git a/Subtrees/beast/modules/beast_core/containers/HashMap.h b/Subtrees/beast/modules/beast_core/containers/HashMap.h
index 3cfb17fcbc..95dd1f4dcf 100644
--- a/Subtrees/beast/modules/beast_core/containers/HashMap.h
+++ b/Subtrees/beast/modules/beast_core/containers/HashMap.h
@@ -100,6 +100,8 @@ private:
namespace detail
{
+struct BucketTag { };
+
template
class HashMapLocalIterator
: public std::iterator
@@ -194,7 +196,7 @@ private:
typedef detail::ListIterator ::Node>::type> bucket_iterator;
typedef detail::ListIterator ::Node>::type> item_iterator;
+ typename List - ::Node>::type> item_iterator;
public:
typedef typename M::Pair value_type;
@@ -202,15 +204,36 @@ public:
typedef value_type& reference;
typedef typename M::size_type size_type;
- HashMapIterator (M* map = nullptr,
- bucket_iterator bucket = bucket_iterator (),
- item_iterator local = item_iterator ())
+ HashMapIterator ()
+ : m_map (nullptr)
+ , m_bucket (bucket_iterator ())
+ , m_local (item_iterator ())
+ {
+ }
+
+ // represents end()
+ explicit HashMapIterator (M* map)
+ : m_map (map)
+ , m_bucket (bucket_iterator ())
+ , m_local (item_iterator ())
+ {
+ }
+
+ HashMapIterator (M* map, bucket_iterator const& bucket, item_iterator const& local)
: m_map (map)
, m_bucket (bucket)
, m_local (local)
{
}
+#if 0
+ HashMapIterator (HashMapIterator const& other) noexcept
+ : m_map (other.m_map)
+ , m_bucket (other.m_bucket)
+ , m_local (other.m_local)
+ {
+ }
+
template
HashMapIterator (HashMapIterator const& other) noexcept
: m_map (other.m_map)
@@ -218,7 +241,7 @@ public:
, m_local (other.m_local)
{
}
-
+#endif
template
HashMapIterator& operator= (HashMapIterator const& other) noexcept
{
@@ -359,7 +382,7 @@ private:
return items.empty ();
}
- List
- items;
+ List
- items;
private:
Bucket& operator= (Bucket const&);
@@ -369,7 +392,7 @@ private:
// Every item in the map is in one linked list
struct Item
: List
- ::Node
- , List
- ::Node
+ , List
- ::Node
{
Item (Pair const& pair_)
: m_pair (pair_)
@@ -403,17 +426,17 @@ public:
typedef value_type& reference;
typedef value_type const* const_pointer;
typedef value_type const& const_reference;
+
+ typedef HashMap container_type;
- typedef detail::HashMapIterator > iterator;
- typedef detail::HashMapIterator const> const_iterator;
+ typedef detail::HashMapIterator iterator;
+ typedef detail::HashMapIterator const_iterator;
- typedef detail::HashMapLocalIterator <
- HashMap ,
- typename List
- ::iterator> local_iterator;
+ typedef detail::HashMapLocalIterator ::iterator> local_iterator;
- typedef detail::HashMapLocalIterator <
- HashMap const,
- typename List
- ::const_iterator> const_local_iterator;
+ typedef detail::HashMapLocalIterator ::const_iterator> const_local_iterator;
//--------------------------------------------------------------------------
@@ -514,17 +537,17 @@ public:
iterator end () noexcept
{
- return iterator (this, m_bucketlist.end ());
+ return iterator (static_cast (this));
}
const_iterator end () const noexcept
{
- return const_iterator (this, m_bucketlist.end ());
+ return const_iterator (this);
}
const_iterator cend () const noexcept
{
- return const_iterator (this, m_bucketlist.cend ());
+ return const_iterator (this);
}
//--------------------------------------------------------------------------
@@ -601,10 +624,10 @@ public:
{
size_type found (0);
Bucket& b (m_buckets [bucket (key)]);
- for (typename List
- ::iterator iter (b.items.begin ());
+ for (typename List
- ::iterator iter (b.items.begin ());
iter != b.items.end ();)
{
- typename List
- ::iterator cur (iter++);
+ typename List
- ::iterator cur (iter++);
if (m_equal (cur->pair ().key (), key))
{
erase (b, cur);
@@ -641,7 +664,7 @@ public:
{
size_type n = 0;
Bucket const& b (m_buckets [bucket (key)]);
- for (typename List
- ::iterator iter = b.items.begin ();
+ for (typename List
- ::iterator iter = b.items.begin ();
iter != b.items.end (); ++iter)
if (m_equal (iter->key (), key))
++n;
@@ -765,16 +788,16 @@ private:
void grow_buckets ()
{
- float const scale = 1.f + (float (percentageIncrease) / 100.f);
- size_type const count (std::ceil (
- (size () / max_load_factor ()) * scale));
+ double const scale = 1. + (double (percentageIncrease) / 100.);
+ size_type const count (size_type (std::ceil (
+ (double (size ()) / double (max_load_factor ())) * scale)));
rehash (count);
}
iterator find (KeyParam key, size_type n) noexcept
{
Bucket& b (m_buckets [n]);
- for (typename List
- ::iterator iter =
+ for (typename List
- ::iterator iter =
b.items.begin (); iter != b.items.end (); ++iter)
if (m_equal (iter->pair ().key (), key))
return iterator (this, m_bucketlist.iterator_to (b), iter);
@@ -784,7 +807,7 @@ private:
const_iterator find (KeyParam key, size_type n) const noexcept
{
Bucket const& b (m_buckets [n]);
- for (typename List
- ::const_iterator iter =
+ for (typename List
- ::const_iterator iter =
b.items.begin (); iter != b.items.end (); ++iter)
if (m_equal (iter->pair ().key (), key))
return const_iterator (this,
@@ -805,7 +828,7 @@ private:
b.items.begin ());
}
- void erase (Bucket& b, typename List
- ::iterator pos)
+ void erase (Bucket& b, typename List
- ::iterator pos)
{
Item& item (*pos);
b.items.erase (b.items.iterator_to (item));
diff --git a/Subtrees/beast/modules/beast_core/containers/List.h b/Subtrees/beast/modules/beast_core/containers/List.h
index 0d96e61d44..2a125ff7da 100644
--- a/Subtrees/beast/modules/beast_core/containers/List.h
+++ b/Subtrees/beast/modules/beast_core/containers/List.h
@@ -236,13 +236,14 @@ public:
: m_node (node)
{
}
-#if 0
+
template
ListIterator (ListIterator const& other) noexcept
: m_node (other.m_node)
{
}
+#if 0
template
ListIterator& operator= (ListIterator const& other) noexcept
{
diff --git a/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h b/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h
index 6b8fc502d2..ac8d74d5c0 100644
--- a/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h
+++ b/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h
@@ -33,13 +33,7 @@ struct copyconst
template
struct copyconst
{
- typedef U const type;
-};
-
-template
-struct copyconst
-{
- typedef U type;
+ typedef typename removecv ::type const type;
};
}
diff --git a/Subtrees/beast/modules/beast_core/diagnostic/beast_UnitTestUtilities.h b/Subtrees/beast/modules/beast_core/diagnostic/beast_UnitTestUtilities.h
index 6f8234b483..2e2df5d962 100644
--- a/Subtrees/beast/modules/beast_core/diagnostic/beast_UnitTestUtilities.h
+++ b/Subtrees/beast/modules/beast_core/diagnostic/beast_UnitTestUtilities.h
@@ -26,18 +26,22 @@ namespace UnitTestUtilities
/** Fairly shuffle an array pseudo-randomly.
*/
template
-void repeatableShuffle (int const numberOfItems, T& arrayOfItems, int64 seedValue)
+void repeatableShuffle (int const numberOfItems, T& arrayOfItems, Random& r)
{
- Random r (seedValue);
-
for (int i = numberOfItems - 1; i > 0; --i)
{
int const choice = r.nextInt (i + 1);
-
std::swap (arrayOfItems [i], arrayOfItems [choice]);
}
}
+template
+void repeatableShuffle (int const numberOfItems, T& arrayOfItems, int64 seedValue)
+{
+ Random r (seedValue);
+ repeatableShuffle (numberOfItems, arrayOfItems, r);
+}
+
//------------------------------------------------------------------------------
/** A block of memory used for test data.