mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Remove obsolete beast container classes
This commit is contained in:
@@ -219,8 +219,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\ArrayAllocationBase.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicObject.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\ElementComparator.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicArray.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\HashMap.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\LinkedListPointer.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\LockFreeQueue.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\NamedValueSet.h" />
|
||||
@@ -228,8 +226,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\PropertySet.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SharedObjectArray.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\ScopedValueSetter.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SharedTable.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SortedLookupTable.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SortedSet.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SparseSet.h" />
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicList.h" />
|
||||
@@ -701,24 +697,12 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\DynamicArray.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\DynamicList.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\HashMap.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\diagnostic\Assert.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -587,12 +587,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\threads\SpinDelay.h">
|
||||
<Filter>beast_core\threads</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SharedTable.h">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\SortedLookupTable.h">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\diagnostic\FPUFlags.h">
|
||||
<Filter>beast_core\diagnostic</Filter>
|
||||
</ClInclude>
|
||||
@@ -827,12 +821,6 @@
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicList.h">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\DynamicArray.h">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\modules\beast_core\containers\HashMap.h">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\intrusive\ForwardList.h">
|
||||
<Filter>beast\intrusive</Filter>
|
||||
</ClInclude>
|
||||
@@ -1634,15 +1622,9 @@
|
||||
<ClCompile Include="..\..\modules\beast_core\system\SystemStats.cpp">
|
||||
<Filter>beast_core\system</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\DynamicArray.cpp">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\DynamicList.cpp">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\HashMap.cpp">
|
||||
<Filter>beast_core\containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\modules\beast_asio\async\SharedHandler.cpp">
|
||||
<Filter>beast_asio\async</Filter>
|
||||
</ClCompile>
|
||||
|
||||
9
TODO.txt
9
TODO.txt
@@ -17,13 +17,6 @@ BEAST TODO
|
||||
|
||||
- Import secp256k1 from sipa
|
||||
|
||||
- HashMap work:
|
||||
- Add unit test
|
||||
- Return size_t from hash function, take out upperLimit, move mod % to caller
|
||||
- Make hash function a functor using operator()
|
||||
- Implement HardenedHashFunctions
|
||||
- Fix problem with assigning to the result of operator[] maybe use a proxy?
|
||||
|
||||
- Set sqlite thread safety model to '2' in beast_sqlite
|
||||
|
||||
- Document and rename all the sqdb files and classes
|
||||
@@ -60,8 +53,6 @@ BEAST TODO
|
||||
|
||||
- Rename malloc/calloc JUCE members that conflict with the debug CRT from MSVC
|
||||
|
||||
- Make beast::HashMap support assignment via operator[]
|
||||
|
||||
- Reformat every Doxygen comment
|
||||
- Fix Doxygen metatags
|
||||
- update Beast Doxyfile
|
||||
|
||||
@@ -134,9 +134,7 @@ namespace beast
|
||||
#include "containers/NamedValueSet.cpp"
|
||||
#include "containers/PropertySet.cpp"
|
||||
#include "containers/Variant.cpp"
|
||||
#include "containers/DynamicArray.cpp"
|
||||
#include "containers/DynamicList.cpp"
|
||||
#include "containers/HashMap.cpp"
|
||||
|
||||
#include "diagnostic/FatalError.cpp"
|
||||
#include "diagnostic/FPUFlags.cpp"
|
||||
|
||||
@@ -177,14 +177,10 @@ class FileOutputStream;
|
||||
#include "containers/PropertySet.h"
|
||||
#include "containers/SharedObjectArray.h"
|
||||
#include "containers/ScopedValueSetter.h"
|
||||
#include "containers/SharedTable.h"
|
||||
#include "containers/SortedLookupTable.h"
|
||||
#include "containers/SortedSet.h"
|
||||
#include "maths/Range.h"
|
||||
#include "containers/SparseSet.h"
|
||||
# include "containers/DynamicList.h"
|
||||
# include "containers/DynamicArray.h"
|
||||
#include "containers/HashMap.h"
|
||||
#include "memory/ScopedPointer.h"
|
||||
#include "files/DirectoryIterator.h"
|
||||
#include "streams/InputStream.h"
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 DynamicArrayTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
struct T
|
||||
{
|
||||
T ()
|
||||
{
|
||||
}
|
||||
|
||||
explicit T (String what)
|
||||
: msg (what)
|
||||
{
|
||||
}
|
||||
|
||||
T& operator= (T const& other)
|
||||
{
|
||||
msg = other.msg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
String msg;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
numberToAssign = 1000 * 1000,
|
||||
numberToReserve = 1000 * 1000,
|
||||
numberToMutate = 12139
|
||||
|
||||
};
|
||||
|
||||
void testAssign ()
|
||||
{
|
||||
String s;
|
||||
s << "assign (" << String::fromNumber <int> (numberToAssign) << ")";
|
||||
beginTestCase (s);
|
||||
|
||||
DynamicArray <T> v;
|
||||
v.assign (numberToAssign);
|
||||
|
||||
pass ();
|
||||
}
|
||||
|
||||
void testReserve ()
|
||||
{
|
||||
String s;
|
||||
s << "reserve (" << String::fromNumber <int> (numberToReserve) << ")";
|
||||
beginTestCase (s);
|
||||
|
||||
DynamicArray <T> v;
|
||||
v.reserve (numberToReserve);
|
||||
|
||||
v.assign (numberToReserve);
|
||||
|
||||
pass ();
|
||||
}
|
||||
|
||||
void testMutate ()
|
||||
{
|
||||
String s;
|
||||
DynamicArray <T> v;
|
||||
|
||||
s = "push_back (" + String::fromNumber <int> (numberToMutate) + ")";
|
||||
beginTestCase (s);
|
||||
for (std::size_t i = 0; i < numberToMutate; ++i)
|
||||
v.push_back (T (String::fromNumber (i)));
|
||||
pass ();
|
||||
|
||||
s = "read [] (" + String::fromNumber <int> (numberToMutate) + ")";
|
||||
beginTestCase (s);
|
||||
for (std::size_t i = 0; i < numberToMutate; ++i)
|
||||
expect (v [i].msg == String::fromNumber (i));
|
||||
|
||||
s = "write [] (" + String::fromNumber <int> (numberToMutate) + ")";
|
||||
beginTestCase (s);
|
||||
for (std::size_t i = 0; i < numberToMutate; ++i)
|
||||
v [i].msg = "+" + String::fromNumber (i);
|
||||
pass ();
|
||||
|
||||
s = "verify [] (" + String::fromNumber <int> (numberToMutate) + ")";
|
||||
beginTestCase (s);
|
||||
for (std::size_t i = 0; i < numberToMutate; ++i)
|
||||
expect (v [i].msg == String ("+") + String::fromNumber (i));
|
||||
}
|
||||
|
||||
void testIterate ()
|
||||
{
|
||||
typedef DynamicArray <T> V;
|
||||
|
||||
V v;
|
||||
for (std::size_t i = 0; i < numberToMutate; ++i)
|
||||
v.push_back (T (String::fromNumber (i)));
|
||||
|
||||
{
|
||||
int step = 1;
|
||||
beginTestCase ("iterator");
|
||||
V::iterator iter;
|
||||
for (iter = v.begin (); iter + step < v.end (); iter += step)
|
||||
{
|
||||
step ++;
|
||||
V::difference_type d = iter - v.begin ();
|
||||
expect (iter->msg == String::fromNumber (d));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int step = 1;
|
||||
beginTestCase ("const_iterator");
|
||||
V::const_iterator iter;
|
||||
for (iter = v.begin (); iter + step < v.end (); iter += step)
|
||||
{
|
||||
step ++;
|
||||
V::difference_type d = iter - v.begin ();
|
||||
expect (iter->msg == String::fromNumber (d));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int step = 1;
|
||||
beginTestCase ("reverse_iterator");
|
||||
V::reverse_iterator iter;
|
||||
for (iter = v.rbegin (); iter + step < v.rend (); iter += step)
|
||||
{
|
||||
step ++;
|
||||
iter - v.rend ();
|
||||
}
|
||||
pass ();
|
||||
}
|
||||
|
||||
{
|
||||
int step = 1;
|
||||
beginTestCase ("const_reverse_iterator");
|
||||
V::const_reverse_iterator iter;
|
||||
for (iter = v.crbegin (); iter + step < v.crend (); iter += step)
|
||||
{
|
||||
step ++;
|
||||
iter - v.crend ();
|
||||
}
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
testAssign ();
|
||||
testReserve ();
|
||||
testMutate ();
|
||||
testIterate ();
|
||||
}
|
||||
|
||||
DynamicArrayTests () : UnitTest ("DynamicArray", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static DynamicArrayTests dynamicArrayTests;
|
||||
@@ -1,728 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED
|
||||
#define BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED
|
||||
|
||||
template <typename, typename>
|
||||
class DynamicArray;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename V>
|
||||
class DynamicArrayIterator
|
||||
: public std::iterator <std::random_access_iterator_tag,
|
||||
typename V::size_type>
|
||||
{
|
||||
public:
|
||||
typedef typename mpl::CopyConst <V, typename V::value_type>::type
|
||||
|
||||
value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef typename V::size_type size_type;
|
||||
|
||||
DynamicArrayIterator (V* v = nullptr, size_type pos = 0) noexcept
|
||||
: m_v (v)
|
||||
, m_pos (pos)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
DynamicArrayIterator (DynamicArrayIterator <W> const& u) noexcept
|
||||
: m_v (u.m_v)
|
||||
, m_pos (u.m_pos)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
DynamicArrayIterator& operator= (DynamicArrayIterator <W> const& u) noexcept
|
||||
{
|
||||
m_v = u.m_v;
|
||||
m_pos = u.m_pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator== (DynamicArrayIterator <W> const& u) const noexcept
|
||||
{
|
||||
return (m_v == u.m_v) && (m_pos == u.m_pos);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator!= (DynamicArrayIterator <W> const& u) const noexcept
|
||||
{
|
||||
return ! ((*this) == u);
|
||||
}
|
||||
|
||||
reference operator* () const noexcept
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const noexcept
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
DynamicArrayIterator& operator++ () noexcept
|
||||
{
|
||||
increment (1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayIterator operator++ (int) noexcept
|
||||
{
|
||||
DynamicArrayIterator const result (*this);
|
||||
increment (1);
|
||||
return result;
|
||||
}
|
||||
|
||||
DynamicArrayIterator& operator-- () noexcept
|
||||
{
|
||||
decrement (1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayIterator operator-- (int) noexcept
|
||||
{
|
||||
DynamicArrayIterator const result (*this);
|
||||
decrement (1);
|
||||
return result;
|
||||
}
|
||||
|
||||
DynamicArrayIterator& operator+= (difference_type n) noexcept
|
||||
{
|
||||
increment (n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayIterator& operator-= (difference_type n) noexcept
|
||||
{
|
||||
decrement (n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayIterator operator+ (difference_type n) noexcept
|
||||
{
|
||||
return DynamicArrayIterator (m_v, m_pos + n);
|
||||
}
|
||||
|
||||
DynamicArrayIterator operator- (difference_type n) noexcept
|
||||
{
|
||||
return DynamicArrayIterator (m_v, m_pos - n);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
difference_type operator- (DynamicArrayIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos - rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator< (DynamicArrayIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos < rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator> (DynamicArrayIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos > rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator<= (DynamicArrayIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos <= rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator>= (DynamicArrayIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos >= rhs.m_pos;
|
||||
}
|
||||
|
||||
reference operator[] (difference_type n) noexcept
|
||||
{
|
||||
return (*m_v)[m_pos + n];
|
||||
}
|
||||
|
||||
private:
|
||||
reference dereference () const noexcept
|
||||
{
|
||||
return (*m_v) [m_pos];
|
||||
}
|
||||
|
||||
void increment (difference_type n) noexcept
|
||||
{
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
void decrement (difference_type n) noexcept
|
||||
{
|
||||
m_pos -= n;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class DynamicArrayIterator;
|
||||
|
||||
V* m_v;
|
||||
size_type m_pos;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename V>
|
||||
DynamicArrayIterator <V> operator+ (
|
||||
typename DynamicArrayIterator <V>::difference_type n,
|
||||
DynamicArrayIterator <V> iter) noexcept
|
||||
{
|
||||
return iter + n;
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
DynamicArrayIterator <V> operator- (
|
||||
typename DynamicArrayIterator <V>::difference_type n,
|
||||
DynamicArrayIterator <V> iter) noexcept
|
||||
{
|
||||
return iter - n;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename V>
|
||||
class DynamicArrayReverseIterator
|
||||
: public std::iterator <std::random_access_iterator_tag,
|
||||
typename V::size_type>
|
||||
{
|
||||
public:
|
||||
typedef typename mpl::CopyConst<V, typename V::value_type>::type
|
||||
|
||||
value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef typename V::size_type size_type;
|
||||
|
||||
DynamicArrayReverseIterator (V* v = nullptr, difference_type pos = 0) noexcept
|
||||
: m_v (v)
|
||||
, m_pos (pos)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
DynamicArrayReverseIterator (DynamicArrayReverseIterator <W> const& u) noexcept
|
||||
: m_v (u.m_v)
|
||||
, m_pos (u.m_pos)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
DynamicArrayReverseIterator& operator= (DynamicArrayReverseIterator <W> const& u) noexcept
|
||||
{
|
||||
m_v = u.m_v;
|
||||
m_pos = u.m_pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator== (DynamicArrayReverseIterator <W> const& u) const noexcept
|
||||
{
|
||||
return (m_v == u.m_v) && (m_pos == u.m_pos);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator!= (DynamicArrayReverseIterator <W> const& u) const noexcept
|
||||
{
|
||||
return ! ((*this) == u);
|
||||
}
|
||||
|
||||
reference operator* () const noexcept
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const noexcept
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator& operator++ () noexcept
|
||||
{
|
||||
increment (1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator operator++ (int) noexcept
|
||||
{
|
||||
DynamicArrayReverseIterator const result (*this);
|
||||
increment (1);
|
||||
return result;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator& operator-- () noexcept
|
||||
{
|
||||
decrement (1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator operator-- (int) noexcept
|
||||
{
|
||||
DynamicArrayReverseIterator const result (*this);
|
||||
decrement (1);
|
||||
return result;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator& operator+= (difference_type n) noexcept
|
||||
{
|
||||
increment (n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator& operator-= (difference_type n) noexcept
|
||||
{
|
||||
decrement (n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator operator+ (difference_type n) noexcept
|
||||
{
|
||||
return DynamicArrayReverseIterator (m_v, m_pos - n);
|
||||
}
|
||||
|
||||
DynamicArrayReverseIterator operator- (difference_type n) noexcept
|
||||
{
|
||||
return DynamicArrayReverseIterator (m_v, m_pos + n);
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
difference_type operator- (DynamicArrayReverseIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return rhs.m_pos - m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator< (DynamicArrayReverseIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos > rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator> (DynamicArrayReverseIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos < rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator<= (DynamicArrayReverseIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos >= rhs.m_pos;
|
||||
}
|
||||
|
||||
template <typename W>
|
||||
bool operator>= (DynamicArrayReverseIterator <W> const& rhs) const noexcept
|
||||
{
|
||||
return m_pos <= rhs.m_pos;
|
||||
}
|
||||
|
||||
reference operator[] (difference_type n) noexcept
|
||||
{
|
||||
return (*m_v)[(m_pos - 1) - n];
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename>
|
||||
friend class DynamicArrayReverseIterator;
|
||||
|
||||
reference dereference () const noexcept
|
||||
{
|
||||
return (*m_v) [m_pos - 1];
|
||||
}
|
||||
|
||||
void increment (difference_type n) noexcept
|
||||
{
|
||||
m_pos -= n;
|
||||
}
|
||||
|
||||
void decrement (difference_type n) noexcept
|
||||
{
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
V* m_v;
|
||||
difference_type m_pos;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename V>
|
||||
DynamicArrayReverseIterator <V> operator+ (
|
||||
typename DynamicArrayReverseIterator <V>::difference_type n,
|
||||
DynamicArrayReverseIterator <V> iter) noexcept
|
||||
{
|
||||
return iter + n;
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
DynamicArrayReverseIterator <V> operator- (
|
||||
typename DynamicArrayReverseIterator <V>::difference_type n,
|
||||
DynamicArrayReverseIterator <V> iter) noexcept
|
||||
{
|
||||
return iter - n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename T,
|
||||
typename Allocator = std::allocator <char> >
|
||||
class DynamicArray
|
||||
{
|
||||
private:
|
||||
typedef PARAMETER_TYPE (T) TParam;
|
||||
|
||||
typedef std::vector <T*> handles_t;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
defaultBlocksize = 1000,
|
||||
growthPercentage = 10
|
||||
};
|
||||
|
||||
typedef T value_type;
|
||||
typedef Allocator allocator_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef value_type const* const_pointer;
|
||||
typedef value_type const& const_reference;
|
||||
|
||||
typedef detail::DynamicArrayIterator <DynamicArray <T> > iterator;
|
||||
|
||||
typedef detail::DynamicArrayIterator <DynamicArray <T> const> const_iterator;
|
||||
|
||||
typedef detail::DynamicArrayReverseIterator <DynamicArray <T> > reverse_iterator;
|
||||
|
||||
typedef detail::DynamicArrayReverseIterator <DynamicArray <T> const> const_reverse_iterator;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
explicit DynamicArray (size_type blocksize = defaultBlocksize) noexcept
|
||||
: m_blocksize (blocksize)
|
||||
, m_capacity (0)
|
||||
, m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
~DynamicArray()
|
||||
{
|
||||
clear ();
|
||||
shrink_to_fit ();
|
||||
}
|
||||
|
||||
/** Replace the array with 'count' copies of a default-constructed T.
|
||||
*/
|
||||
void assign (size_type count)
|
||||
{
|
||||
clear ();
|
||||
resize (count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
reference at (size_type pos)
|
||||
{
|
||||
if (pos >= size ())
|
||||
Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__);
|
||||
return get (pos);
|
||||
}
|
||||
|
||||
const_reference at (size_type pos) const
|
||||
{
|
||||
if (pos >= size ())
|
||||
Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__);
|
||||
return get (pos);
|
||||
}
|
||||
|
||||
reference operator[] (size_type pos) noexcept
|
||||
{
|
||||
return get (pos);
|
||||
}
|
||||
|
||||
const_reference operator[] (size_type pos) const noexcept
|
||||
{
|
||||
return get (pos);
|
||||
}
|
||||
|
||||
reference front () noexcept
|
||||
{
|
||||
return get (0);
|
||||
}
|
||||
|
||||
const_reference front () const noexcept
|
||||
{
|
||||
return get (0);
|
||||
}
|
||||
|
||||
reference back () noexcept
|
||||
{
|
||||
return get (size () - 1);
|
||||
}
|
||||
|
||||
const_reference back () const noexcept
|
||||
{
|
||||
return get (size () - 1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
iterator begin () noexcept
|
||||
{
|
||||
return iterator (this, 0);
|
||||
}
|
||||
|
||||
const_iterator begin () const noexcept
|
||||
{
|
||||
return const_iterator (this, 0);
|
||||
}
|
||||
|
||||
const_iterator cbegin () const noexcept
|
||||
{
|
||||
return const_iterator (this, 0);
|
||||
}
|
||||
|
||||
iterator end () noexcept
|
||||
{
|
||||
return iterator (this, size ());
|
||||
}
|
||||
|
||||
const_iterator end () const noexcept
|
||||
{
|
||||
return const_iterator (this, size ());
|
||||
}
|
||||
|
||||
const_iterator cend () const noexcept
|
||||
{
|
||||
return const_iterator (this, size ());
|
||||
}
|
||||
|
||||
reverse_iterator rbegin () noexcept
|
||||
{
|
||||
return reverse_iterator (this, size ());
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin () const noexcept
|
||||
{
|
||||
return const_reverse_iterator (this, size ());
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin () const noexcept
|
||||
{
|
||||
return const_reverse_iterator (this, size ());
|
||||
}
|
||||
|
||||
reverse_iterator rend () noexcept
|
||||
{
|
||||
return reverse_iterator (this, 0);
|
||||
}
|
||||
|
||||
const_reverse_iterator rend () const noexcept
|
||||
{
|
||||
return const_reverse_iterator (this, 0);
|
||||
}
|
||||
|
||||
const_reverse_iterator crend () const noexcept
|
||||
{
|
||||
return const_reverse_iterator (this, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool empty () const noexcept
|
||||
{
|
||||
return m_size == 0;
|
||||
}
|
||||
|
||||
size_type size () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_type max_size () const noexcept
|
||||
{
|
||||
return std::numeric_limits <size_type>::max ();
|
||||
}
|
||||
|
||||
void reserve (size_type new_cap)
|
||||
{
|
||||
new_cap = m_blocksize * (
|
||||
(new_cap + m_blocksize - 1) / m_blocksize);
|
||||
if (new_cap > max_size ())
|
||||
Throw (std::length_error ("new_cap > max_size"), __FILE__, __LINE__);
|
||||
if (new_cap <= m_capacity)
|
||||
return;
|
||||
size_type const n (new_cap / m_blocksize);
|
||||
m_handles.reserve (n);
|
||||
for (size_type i = m_handles.size (); i < n; ++i)
|
||||
m_handles.push_back (static_cast <T*> (std::malloc (
|
||||
m_blocksize * sizeof (T))));
|
||||
m_capacity = new_cap;
|
||||
}
|
||||
|
||||
size_type capacity () const noexcept
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
void shrink_to_fit ()
|
||||
{
|
||||
size_type const handles (
|
||||
(size () + m_blocksize - 1) / m_blocksize);
|
||||
m_capacity = handles * m_blocksize;
|
||||
for (size_type i = m_handles.size (); i-- > handles;)
|
||||
{
|
||||
std::free (m_handles [i]);
|
||||
m_handles.erase (m_handles.begin () + i);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void clear ()
|
||||
{
|
||||
resize (0);
|
||||
}
|
||||
|
||||
iterator push_back (TParam value)
|
||||
{
|
||||
new (alloc ()) T (value);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
iterator emplace_back ()
|
||||
{
|
||||
new (alloc ()) T ();
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
template <class A1>
|
||||
iterator emplace_back (A1 a1)
|
||||
{
|
||||
new (alloc ()) T (a1);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
template <class A1, class A2>
|
||||
iterator emplace_back (A1 a1, A2 a2)
|
||||
{
|
||||
new (alloc ()) T (a1, a2);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3>
|
||||
iterator emplace_back (A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
new (alloc ()) T (a1, a2, a3);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4>
|
||||
iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4)
|
||||
{
|
||||
new (alloc ()) T (a1, a2, a3, a4);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
template <class A1, class A2, class A3, class A4, class A5>
|
||||
iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
|
||||
{
|
||||
new (alloc ()) T (a1, a2, a3, a4, a5);
|
||||
return iterator (this, size () - 1);
|
||||
}
|
||||
|
||||
void pop_back ()
|
||||
{
|
||||
resize (size () - 1);
|
||||
}
|
||||
|
||||
void resize (size_type count)
|
||||
{
|
||||
while (count > size ())
|
||||
new (alloc ()) T;
|
||||
|
||||
while (count < size ())
|
||||
get (--m_size).~T ();
|
||||
}
|
||||
|
||||
void resize (size_type count, TParam value)
|
||||
{
|
||||
while (count > size ())
|
||||
new (alloc ()) T (value);
|
||||
|
||||
while (count < size ())
|
||||
get (--m_size).~T ();
|
||||
}
|
||||
|
||||
void swap (DynamicArray& other)
|
||||
{
|
||||
std::swap (m_blocksize, other.m_blocksize);
|
||||
std::swap (m_size, other.m_size);
|
||||
std::swap (m_capacity, other.m_capacity);
|
||||
std::swap (m_handles, other.m_handles);
|
||||
}
|
||||
|
||||
private:
|
||||
reference get (size_type pos) noexcept
|
||||
{
|
||||
size_type const index (pos / m_blocksize);
|
||||
size_type const offset (pos % m_blocksize);
|
||||
return m_handles [index] [offset];
|
||||
}
|
||||
|
||||
const_reference get (size_type pos) const noexcept
|
||||
{
|
||||
size_type const index (pos / m_blocksize);
|
||||
size_type const offset (pos % m_blocksize);
|
||||
return m_handles [index] [offset];
|
||||
}
|
||||
|
||||
T* alloc () noexcept
|
||||
{
|
||||
size_type const needed (size () + 1);
|
||||
if (capacity () < needed)
|
||||
reserve ((needed * (100 + growthPercentage) + 99) / 100);
|
||||
return &get (m_size++);
|
||||
}
|
||||
|
||||
private:
|
||||
Allocator m_allocator;
|
||||
size_type m_blocksize;
|
||||
size_type m_capacity;
|
||||
size_type m_size;
|
||||
handles_t m_handles;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,154 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 <int keyBytes>
|
||||
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 <Key> m_keys;
|
||||
std::vector <Key*> m_shuffled_keys;
|
||||
};
|
||||
|
||||
template <int keyBytes>
|
||||
void testInsert (std::size_t numberOfKeys, Random& random)
|
||||
{
|
||||
beginTestCase (String
|
||||
("insertion, numberOfKeys = ") + String::fromNumber (numberOfKeys) +
|
||||
", keyBytes = " + String::fromNumber (keyBytes));
|
||||
|
||||
typedef TestTraits <keyBytes> 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));
|
||||
|
||||
String s (
|
||||
"load_factor = " + String::fromNumber (map.load_factor (), 2) +
|
||||
", bucket_count = " + String::fromNumber (map.bucket_count ()));
|
||||
this->logMessage (s);
|
||||
|
||||
expect (map.size () == numberOfKeys);
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
int64 const seedValue = 072472;
|
||||
Random random (seedValue);
|
||||
testInsert <4> (numberOfItems, random);
|
||||
testInsert <20> (numberOfItems, random);
|
||||
}
|
||||
|
||||
HashMapTests () : UnitTest ("HashMap", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static HashMapTests hashMapTests;
|
||||
@@ -1,856 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.com
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HASHMAP_H_INCLUDED
|
||||
#define BEAST_HASHMAP_H_INCLUDED
|
||||
|
||||
/** The integral type for holding a non cryptographic hash.
|
||||
HashValue is used for fast comparisons, bloom filters, and hash maps.
|
||||
*/
|
||||
typedef uint32 HashValue;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Simple hash functions for use with HashMap.
|
||||
|
||||
@see HashMap
|
||||
*/
|
||||
// VFALCO TODO Rewrite the hash functions to return a uint32, and not
|
||||
// take the upperLimit parameter. Just do the mod in the
|
||||
// calling function for simplicity.
|
||||
class DefaultHashFunctions
|
||||
{
|
||||
public:
|
||||
/** Generates a simple hash from an integer. */
|
||||
HashValue generateHash (const int key) const noexcept
|
||||
{
|
||||
return HashValue (std::abs (key));
|
||||
}
|
||||
|
||||
/** Generates a simple hash from an int64. */
|
||||
HashValue generateHash (const int64 key) const noexcept
|
||||
{
|
||||
return HashValue (key);
|
||||
}
|
||||
|
||||
/** Generates a simple hash from a string. */
|
||||
HashValue generateHash (const String& key) const noexcept
|
||||
{
|
||||
return HashValue (key.hashCode ());
|
||||
}
|
||||
|
||||
/** Generates a simple hash from a variant. */
|
||||
HashValue generateHash (const var& key) const noexcept
|
||||
{
|
||||
return generateHash (key.toString ());
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
/** Hardened hash functions for use with HashMap.
|
||||
|
||||
The seed is used to make the hash unpredictable. This prevents
|
||||
attackers from exploiting crafted inputs to produce degenerate
|
||||
containers.
|
||||
*/
|
||||
class HardenedHashFunctions
|
||||
{
|
||||
public:
|
||||
/** Construct a hash function.
|
||||
|
||||
If a seed is specified it will be used, else a random seed
|
||||
will be generated from the system.
|
||||
|
||||
@param seedToUse An optional seed to use.
|
||||
*/
|
||||
explicit HardenedHashFunctions (int seedToUse = Random::getSystemRandom ().nextInt ())
|
||||
: m_seed (seedToUse)
|
||||
{
|
||||
}
|
||||
|
||||
// VFALCO TODO Need hardened versions of these functions which use the seed!
|
||||
|
||||
private:
|
||||
int m_seed;
|
||||
};
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct BucketTag { };
|
||||
|
||||
template <typename M, typename I>
|
||||
class HashMapLocalIterator
|
||||
: public std::iterator <std::forward_iterator_tag, typename M::size_type>
|
||||
{
|
||||
public:
|
||||
typedef typename M::Pair value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef typename M::size_type size_type;
|
||||
|
||||
HashMapLocalIterator (M* map = nullptr, I iter = I ())
|
||||
: m_map (map)
|
||||
, m_iter (iter)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename N, typename J>
|
||||
HashMapLocalIterator (HashMapLocalIterator <N, J> const& other)
|
||||
: m_map (other.m_map)
|
||||
, m_iter (other.m_iter)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename N, typename J>
|
||||
HashMapLocalIterator& operator= (HashMapLocalIterator <N, J> const& other)
|
||||
{
|
||||
m_map = other.m_map;
|
||||
m_iter = other.m_iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename N, typename J>
|
||||
bool operator== (HashMapLocalIterator <N, J> const& other)
|
||||
{
|
||||
return m_map == other.m_map && m_iter == other.m_iter;
|
||||
}
|
||||
|
||||
template <typename N, typename J>
|
||||
bool operator!= (HashMapLocalIterator <N, J> const& other)
|
||||
{
|
||||
return ! ((*this)==other);
|
||||
}
|
||||
|
||||
reference operator* () const noexcept
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const noexcept
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
HashMapLocalIterator& operator++ () noexcept
|
||||
{
|
||||
increment ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HashMapLocalIterator operator++ (int) noexcept
|
||||
{
|
||||
HashMapLocalIterator const result (*this);
|
||||
increment ();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
reference dereference () const noexcept
|
||||
{
|
||||
return m_iter->pair ();
|
||||
}
|
||||
|
||||
void increment () noexcept
|
||||
{
|
||||
++m_iter;
|
||||
}
|
||||
|
||||
M* m_map;
|
||||
I m_iter;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <typename M>
|
||||
class HashMapIterator
|
||||
: public std::iterator <std::forward_iterator_tag, typename M::size_type>
|
||||
{
|
||||
private:
|
||||
typedef typename M::Item Item;
|
||||
typedef typename M::Bucket Bucket;
|
||||
typedef detail::ListIterator <typename mpl::CopyConst <M,
|
||||
typename List <Bucket>::Node>::type> bucket_iterator;
|
||||
typedef detail::ListIterator <typename mpl::CopyConst <M,
|
||||
typename List <Item, detail::BucketTag>::Node>::type> item_iterator;
|
||||
|
||||
public:
|
||||
typedef typename M::Pair value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef typename M::size_type size_type;
|
||||
|
||||
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 <typename N>
|
||||
HashMapIterator (HashMapIterator <N> const& other) noexcept
|
||||
: m_map (other.m_map)
|
||||
, m_bucket (other.m_bucket)
|
||||
, m_local (other.m_local)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
template <typename N>
|
||||
HashMapIterator& operator= (HashMapIterator <N> const& other) noexcept
|
||||
{
|
||||
m_map = other.m_map;
|
||||
m_bucket = other.m_bucket;
|
||||
m_local = other.m_local;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
bool operator== (HashMapIterator <N> const& other) noexcept
|
||||
{
|
||||
return m_map == other.m_map &&
|
||||
m_bucket == other.m_bucket &&
|
||||
m_local == other.m_local;
|
||||
}
|
||||
|
||||
template <typename N>
|
||||
bool operator!= (HashMapIterator <N> const& other) noexcept
|
||||
{
|
||||
return ! ((*this) == other);
|
||||
}
|
||||
|
||||
reference operator* () const noexcept
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const noexcept
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
HashMapIterator& operator++ () noexcept
|
||||
{
|
||||
increment ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HashMapIterator operator++ (int) noexcept
|
||||
{
|
||||
HashMapIterator const result (*this);
|
||||
increment ();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename, typename, typename, typename, typename>
|
||||
friend class HashMap;
|
||||
|
||||
reference dereference () const noexcept
|
||||
{
|
||||
return m_local->pair ();
|
||||
}
|
||||
|
||||
void increment () noexcept
|
||||
{
|
||||
++m_local;
|
||||
if (m_local == m_bucket->items.end ())
|
||||
{
|
||||
++m_bucket;
|
||||
if (m_bucket != m_map->m_bucketlist.end ())
|
||||
m_local = m_bucket->items.begin ();
|
||||
}
|
||||
}
|
||||
|
||||
M* m_map;
|
||||
bucket_iterator m_bucket;
|
||||
item_iterator m_local;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Associative container mapping Key to T pairs.
|
||||
*/
|
||||
template <typename Key,
|
||||
typename T,
|
||||
typename Hash = DefaultHashFunctions,
|
||||
typename KeyEqual = std::equal_to <Key>,
|
||||
typename Allocator = std::allocator <char> >
|
||||
class HashMap
|
||||
{
|
||||
private:
|
||||
typedef PARAMETER_TYPE (Key) KeyParam;
|
||||
typedef PARAMETER_TYPE (T) TParam;
|
||||
|
||||
public:
|
||||
struct Pair
|
||||
{
|
||||
explicit Pair (Key key)
|
||||
: m_key (key)
|
||||
{
|
||||
}
|
||||
|
||||
Pair (Key key, T t)
|
||||
: m_key (key)
|
||||
, m_t (t)
|
||||
{
|
||||
}
|
||||
|
||||
Key const& key () const noexcept
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
T& value () noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
|
||||
T const& value () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
Key m_key;
|
||||
T m_t;
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename M, typename I>
|
||||
friend class detail::HashMapLocalIterator;
|
||||
|
||||
class Item;
|
||||
|
||||
// Each non-empty bucket is in the linked list.
|
||||
struct Bucket : List <Bucket>::Node
|
||||
{
|
||||
Bucket ()
|
||||
{
|
||||
}
|
||||
|
||||
inline bool empty () const noexcept
|
||||
{
|
||||
return items.empty ();
|
||||
}
|
||||
|
||||
List <Item, detail::BucketTag> items;
|
||||
|
||||
private:
|
||||
Bucket& operator= (Bucket const&);
|
||||
Bucket (Bucket const&);
|
||||
};
|
||||
|
||||
// Every item in the map is in one linked list
|
||||
struct Item
|
||||
: List <Item>::Node
|
||||
, List <Item, detail::BucketTag>::Node
|
||||
{
|
||||
Item (Pair const& pair_)
|
||||
: m_pair (pair_)
|
||||
{
|
||||
}
|
||||
|
||||
Pair& pair () noexcept
|
||||
{
|
||||
return m_pair;
|
||||
}
|
||||
|
||||
Pair const& pair () const noexcept
|
||||
{
|
||||
return m_pair;
|
||||
}
|
||||
|
||||
private:
|
||||
Pair m_pair;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Key key_type;
|
||||
typedef T mapped_type;
|
||||
typedef Pair value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef Hash hasher;
|
||||
typedef KeyEqual key_equal;
|
||||
typedef Allocator allocator_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef value_type const* const_pointer;
|
||||
typedef value_type const& const_reference;
|
||||
|
||||
typedef HashMap <Key, T, Hash, KeyEqual, Allocator> container_type;
|
||||
|
||||
typedef detail::HashMapIterator <container_type> iterator;
|
||||
typedef detail::HashMapIterator <container_type const> const_iterator;
|
||||
|
||||
typedef detail::HashMapLocalIterator <container_type,
|
||||
typename List <Item, detail::BucketTag>::iterator> local_iterator;
|
||||
|
||||
typedef detail::HashMapLocalIterator <container_type const,
|
||||
typename List <Item, detail::BucketTag>::const_iterator> const_local_iterator;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
initialBucketCount = 101,
|
||||
percentageIncrease = 25
|
||||
};
|
||||
|
||||
static float getDefaultLoadFactor () noexcept
|
||||
{
|
||||
return 1.2f;
|
||||
}
|
||||
|
||||
explicit HashMap (
|
||||
size_type bucket_count = initialBucketCount,
|
||||
KeyEqual const& equal = KeyEqual (),
|
||||
Hash const& hash = Hash (),
|
||||
Allocator const& allocator = Allocator ())
|
||||
: m_hash (hash)
|
||||
, m_equal (equal)
|
||||
, m_allocator (allocator)
|
||||
, m_max_load_factor (getDefaultLoadFactor ())
|
||||
{
|
||||
rehash (bucket_count);
|
||||
}
|
||||
|
||||
HashMap (
|
||||
size_type bucket_count,
|
||||
Allocator const& allocator = Allocator ())
|
||||
: m_allocator (allocator)
|
||||
, m_max_load_factor (getDefaultLoadFactor ())
|
||||
{
|
||||
rehash (bucket_count);
|
||||
}
|
||||
|
||||
HashMap (
|
||||
size_type bucket_count,
|
||||
Hash const& hash = Hash (),
|
||||
Allocator const& allocator = Allocator ())
|
||||
: m_hash (hash)
|
||||
, m_allocator (allocator)
|
||||
, m_max_load_factor (getDefaultLoadFactor ())
|
||||
{
|
||||
rehash (bucket_count);
|
||||
}
|
||||
|
||||
explicit HashMap (Allocator const& allocator)
|
||||
: m_allocator (allocator)
|
||||
, m_max_load_factor (getDefaultLoadFactor ())
|
||||
{
|
||||
rehash (initialBucketCount);
|
||||
}
|
||||
|
||||
~HashMap()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
HashMap& operator= (HashMap const& other)
|
||||
{
|
||||
clear ();
|
||||
for (iterator iter = other.begin (); iter != other.end (); ++iter)
|
||||
(*this)[iter->key ()] = iter->value ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator () const noexcept
|
||||
{
|
||||
return m_allocator;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
iterator begin () noexcept
|
||||
{
|
||||
if (m_bucketlist.size () > 0)
|
||||
return iterator (this, m_bucketlist.begin (),
|
||||
m_bucketlist.front ().items.begin ());
|
||||
return end ();
|
||||
}
|
||||
|
||||
const_iterator begin () const noexcept
|
||||
{
|
||||
if (m_bucketlist.size () > 0)
|
||||
return const_iterator (this, m_bucketlist.begin (),
|
||||
m_bucketlist.front ().items.begin ());
|
||||
return end ();
|
||||
}
|
||||
|
||||
const_iterator cbegin () const noexcept
|
||||
{
|
||||
if (m_bucketlist.size () > 0)
|
||||
return const_iterator (this, m_bucketlist.begin (),
|
||||
m_bucketlist.front ().items.begin ());
|
||||
return end ();
|
||||
}
|
||||
|
||||
iterator end () noexcept
|
||||
{
|
||||
return iterator (static_cast <container_type*> (this));
|
||||
}
|
||||
|
||||
const_iterator end () const noexcept
|
||||
{
|
||||
return const_iterator (this);
|
||||
}
|
||||
|
||||
const_iterator cend () const noexcept
|
||||
{
|
||||
return const_iterator (this);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool empty () const noexcept
|
||||
{
|
||||
return size () == 0;
|
||||
}
|
||||
|
||||
size_type size () const noexcept
|
||||
{
|
||||
return m_itemlist.size ();
|
||||
}
|
||||
|
||||
size_type max_size () const noexcept
|
||||
{
|
||||
return std::numeric_limits <size_type>::max ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (typename DynamicList <Item>::iterator iter = m_items.begin ();
|
||||
iter != m_items.end ();)
|
||||
{
|
||||
typename DynamicList <Item>::iterator const cur (iter++);
|
||||
m_items.erase (cur);
|
||||
}
|
||||
|
||||
m_itemlist.clear ();
|
||||
m_bucketlist.clear ();
|
||||
size_type const count (m_buckets.size ());
|
||||
m_buckets.assign (count);
|
||||
}
|
||||
|
||||
struct Result
|
||||
{
|
||||
Result (iterator iter_ = iterator (), bool inserted_ = false)
|
||||
: iter (iter_)
|
||||
, inserted (inserted_)
|
||||
{
|
||||
}
|
||||
|
||||
iterator iter;
|
||||
bool inserted;
|
||||
};
|
||||
|
||||
Result insert (Pair const& p)
|
||||
{
|
||||
size_type const n (bucket (p.key ()));
|
||||
iterator iter (find (p.key (), n));
|
||||
if (iter != end ())
|
||||
return Result (iter, false);
|
||||
check_load ();
|
||||
return Result (store (*m_items.emplace_back (p), n), true);
|
||||
}
|
||||
|
||||
Result insert (KeyParam key)
|
||||
{
|
||||
return insert (Pair (key));
|
||||
}
|
||||
|
||||
iterator erase (const_iterator pos)
|
||||
{
|
||||
iterator iter = pos;
|
||||
++iter;
|
||||
Bucket& b (*pos.m_iter);
|
||||
erase (b, pos->m_local);
|
||||
return iter;
|
||||
}
|
||||
|
||||
size_type erase (KeyParam key)
|
||||
{
|
||||
size_type found (0);
|
||||
Bucket& b (m_buckets [bucket (key)]);
|
||||
for (typename List <Item, detail::BucketTag>::iterator iter (b.items.begin ());
|
||||
iter != b.items.end ();)
|
||||
{
|
||||
typename List <Item, detail::BucketTag>::iterator cur (iter++);
|
||||
if (m_equal (cur->pair ().key (), key))
|
||||
{
|
||||
erase (b, cur);
|
||||
++found;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
T& at (KeyParam key)
|
||||
{
|
||||
iterator const iter (find (key));
|
||||
if (iter == end ())
|
||||
Throw (std::out_of_range ("key not found"), __FILE__, __LINE__);
|
||||
return iter->value ();
|
||||
}
|
||||
|
||||
T const& at (KeyParam key) const
|
||||
{
|
||||
const_iterator const iter (find (key));
|
||||
if (iter == end ())
|
||||
Throw (std::out_of_range ("key not found"), __FILE__, __LINE__);
|
||||
return iter->value ();
|
||||
}
|
||||
|
||||
T& operator[] (KeyParam key) noexcept
|
||||
{
|
||||
return insert (key).iter->value ();
|
||||
}
|
||||
|
||||
size_type count (KeyParam key) const noexcept
|
||||
{
|
||||
size_type n = 0;
|
||||
Bucket const& b (m_buckets [bucket (key)]);
|
||||
for (typename List <Item, detail::BucketTag>::iterator iter = b.items.begin ();
|
||||
iter != b.items.end (); ++iter)
|
||||
if (m_equal (iter->key (), key))
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
iterator find (KeyParam key) noexcept
|
||||
{
|
||||
return find (key, bucket (key));
|
||||
}
|
||||
|
||||
const_iterator find (KeyParam key) const noexcept
|
||||
{
|
||||
return find (key, bucket (key));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
local_iterator begin (size_type n) noexcept
|
||||
{
|
||||
return local_iterator (this, m_buckets [n].items.begin ());
|
||||
}
|
||||
|
||||
const_local_iterator begin (size_type n) const noexcept
|
||||
{
|
||||
return const_local_iterator (this, m_buckets [n].items.begin ());
|
||||
}
|
||||
|
||||
const_local_iterator cbegin (size_type n) const noexcept
|
||||
{
|
||||
return const_local_iterator (this, m_buckets [n].items.cbegin ());
|
||||
}
|
||||
|
||||
local_iterator end (size_type n) noexcept
|
||||
{
|
||||
return local_iterator (this, m_buckets [n].items.end ());
|
||||
}
|
||||
|
||||
const_local_iterator end (size_type n) const noexcept
|
||||
{
|
||||
return const_local_iterator (this, m_buckets [n].items.end ());
|
||||
}
|
||||
|
||||
const_local_iterator cend (size_type n) const noexcept
|
||||
{
|
||||
return const_local_iterator (this, m_buckets [n].items.cend ());
|
||||
}
|
||||
|
||||
size_type bucket_count () const noexcept
|
||||
{
|
||||
return m_buckets.size ();
|
||||
}
|
||||
|
||||
size_type max_bucket_count () const noexcept
|
||||
{
|
||||
return std::numeric_limits <size_type>::max ();
|
||||
}
|
||||
|
||||
size_type bucket_size (size_type n) const noexcept
|
||||
{
|
||||
return m_buckets [n].items.size ();
|
||||
}
|
||||
|
||||
size_type bucket (KeyParam key) const noexcept
|
||||
{
|
||||
HashValue const hash (m_hash.generateHash (key));
|
||||
return hash % bucket_count ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
float load_factor () const noexcept
|
||||
{
|
||||
return float (m_items.size ()) / float (m_buckets.size ());
|
||||
}
|
||||
|
||||
float max_load_factor () const noexcept
|
||||
{
|
||||
return m_max_load_factor;
|
||||
}
|
||||
|
||||
void max_load_factor (float ml) noexcept
|
||||
{
|
||||
m_max_load_factor = ml;
|
||||
check_load ();
|
||||
}
|
||||
|
||||
void rehash (size_type const count)
|
||||
{
|
||||
m_bucketlist.clear ();
|
||||
m_buckets.assign (count);
|
||||
for (typename List <Item>::iterator iter = m_itemlist.begin ();
|
||||
iter != m_itemlist.end (); ++iter)
|
||||
{
|
||||
Item& item (*iter);
|
||||
size_type const n (bucket (item.pair ().key ()));
|
||||
Bucket& b (m_buckets [n]);
|
||||
if (b.empty ())
|
||||
m_bucketlist.push_front (b);
|
||||
b.items.push_front (item);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve (size_type count)
|
||||
{
|
||||
m_items.reserve (count);
|
||||
rehash (std::ceil (count / max_load_factor ()));
|
||||
}
|
||||
|
||||
private:
|
||||
// rehashes if adding one more item would put us over
|
||||
void check_load () noexcept
|
||||
{
|
||||
if ( (float (m_items.size () + 1) /
|
||||
float (m_buckets.size ())) >=
|
||||
max_load_factor ())
|
||||
{
|
||||
grow_buckets ();
|
||||
}
|
||||
}
|
||||
|
||||
void grow_buckets ()
|
||||
{
|
||||
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 <Item, detail::BucketTag>::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);
|
||||
return end ();
|
||||
}
|
||||
|
||||
const_iterator find (KeyParam key, size_type n) const noexcept
|
||||
{
|
||||
Bucket const& b (m_buckets [n]);
|
||||
for (typename List <Item, detail::BucketTag>::const_iterator iter =
|
||||
b.items.begin (); iter != b.items.end (); ++iter)
|
||||
if (m_equal (iter->pair ().key (), key))
|
||||
return const_iterator (this,
|
||||
m_bucketlist.const_iterator_to (b), iter);
|
||||
return end ();
|
||||
}
|
||||
|
||||
iterator store (Item& item, size_type n)
|
||||
{
|
||||
check_load ();
|
||||
Bucket& b (m_buckets [n]);
|
||||
if (b.empty ())
|
||||
m_bucketlist.push_front (b);
|
||||
b.items.push_front (item);
|
||||
m_itemlist.push_front (item);
|
||||
return iterator (this,
|
||||
m_bucketlist.iterator_to (b),
|
||||
b.items.begin ());
|
||||
}
|
||||
|
||||
void erase (Bucket& b, typename List <Item, detail::BucketTag>::iterator pos)
|
||||
{
|
||||
Item& item (*pos);
|
||||
b.items.erase (b.items.iterator_to (item));
|
||||
if (b.empty ())
|
||||
m_bucketlist.erase (m_bucketlist.iterator_to (b));
|
||||
m_itemlist.erase (m_itemlist.iterator_to (item));
|
||||
m_items.erase (m_items.iterator_to (item));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename M>
|
||||
friend class detail::HashMapIterator;
|
||||
|
||||
Hash m_hash;
|
||||
KeyEqual m_equal;
|
||||
Allocator m_allocator;
|
||||
DynamicList <Item> m_items;
|
||||
DynamicArray <Bucket> m_buckets;
|
||||
List <Item> m_itemlist;
|
||||
List <Bucket> m_bucketlist;
|
||||
float m_max_load_factor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SHAREDTABLE_H_INCLUDED
|
||||
#define BEAST_SHAREDTABLE_H_INCLUDED
|
||||
|
||||
/** Handle to a reference counted fixed size table.
|
||||
|
||||
@note Currently, ElementType must be an aggregate of POD.
|
||||
|
||||
@tparam ElementType The type of element.
|
||||
|
||||
@ingroup beast_basics
|
||||
*/
|
||||
template <class ElementType>
|
||||
class SharedTable
|
||||
{
|
||||
public:
|
||||
typedef ElementType Entry;
|
||||
|
||||
static SharedTable <ElementType> const null;
|
||||
|
||||
/** Creates a null table.
|
||||
*/
|
||||
SharedTable ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a table with the specified number of entries.
|
||||
|
||||
The entries are uninitialized.
|
||||
|
||||
@param numEntries The number of entries in the table.
|
||||
|
||||
@todo Initialize the data if ElementType is not POD.
|
||||
*/
|
||||
explicit SharedTable (int numEntries)
|
||||
: m_data (new Data (numEntries))
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a shared reference to another table.
|
||||
*/
|
||||
SharedTable (SharedTable const& other)
|
||||
: m_data (other.m_data)
|
||||
{
|
||||
}
|
||||
|
||||
/** Makes this table refer to another table.
|
||||
*/
|
||||
SharedTable& operator= (SharedTable const& other)
|
||||
{
|
||||
m_data = other.m_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
SharedTable (SharedTable&& other) noexcept
|
||||
: m_data (static_cast < typename Data::Ptr&& > (other.m_data))
|
||||
{
|
||||
}
|
||||
|
||||
SharedTable& operator= (SharedTable && other) noexcept
|
||||
{
|
||||
m_data = static_cast < typename Data::Ptr && > (other.m_data);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Destructor.
|
||||
*/
|
||||
~SharedTable ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns true if the two tables share the same set of entries.
|
||||
*/
|
||||
bool operator== (SharedTable const& other) const noexcept
|
||||
{
|
||||
return m_data == other.m_data;
|
||||
}
|
||||
|
||||
/** Returns true if the two tables do not share the same set of entries.
|
||||
*/
|
||||
bool operator!= (SharedTable const& other) const noexcept
|
||||
{
|
||||
return m_data != other.m_data;
|
||||
}
|
||||
|
||||
/** Returns true if the table is not null.
|
||||
*/
|
||||
inline bool isValid () const noexcept
|
||||
{
|
||||
return m_data != nullptr;
|
||||
}
|
||||
|
||||
/** Returns true if the table is null.
|
||||
*/
|
||||
inline bool isNull () const noexcept
|
||||
{
|
||||
return m_data == nullptr;
|
||||
}
|
||||
|
||||
/** Returns the number of tables referring to the same shared entries.
|
||||
*/
|
||||
int getReferenceCount () const noexcept
|
||||
{
|
||||
return m_data == nullptr ? 0 : m_data->getReferenceCount ();
|
||||
}
|
||||
|
||||
/** Create a physical duplicate of the table.
|
||||
*/
|
||||
SharedTable createCopy () const
|
||||
{
|
||||
return SharedTable (m_data != nullptr ? m_data->clone () : nullptr);
|
||||
}
|
||||
|
||||
/** Makes sure no other tables share the same entries as this table.
|
||||
*/
|
||||
void duplicateIfShared ()
|
||||
{
|
||||
if (m_data != nullptr && m_data->getReferenceCount () > 1)
|
||||
m_data = m_data->clone ();
|
||||
}
|
||||
|
||||
/** Return the number of entries in this table.
|
||||
*/
|
||||
inline int getNumEntries () const noexcept
|
||||
{
|
||||
return m_data->getNumEntries ();
|
||||
}
|
||||
|
||||
/** Retrieve a table entry.
|
||||
|
||||
@param index The index of the entry, from 0 to getNumEntries ().
|
||||
*/
|
||||
inline ElementType& operator [] (int index) const noexcept
|
||||
{
|
||||
return m_data->getReference (index);
|
||||
}
|
||||
|
||||
private:
|
||||
class Data : public SharedObject
|
||||
{
|
||||
public:
|
||||
typedef SharedPtr <Data> Ptr;
|
||||
|
||||
explicit Data (int numEntries)
|
||||
: m_numEntries (numEntries)
|
||||
, m_table (numEntries)
|
||||
{
|
||||
}
|
||||
|
||||
inline Data* clone () const
|
||||
{
|
||||
Data* data = new Data (m_numEntries);
|
||||
|
||||
memcpy (
|
||||
data->m_table.getData (),
|
||||
m_table.getData (),
|
||||
m_numEntries * sizeof (ElementType));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
inline int getNumEntries () const
|
||||
{
|
||||
return m_numEntries;
|
||||
}
|
||||
|
||||
inline ElementType& getReference (int index) const
|
||||
{
|
||||
bassert (index >= 0 && index < m_numEntries);
|
||||
return m_table [index];
|
||||
}
|
||||
|
||||
private:
|
||||
int const m_numEntries;
|
||||
HeapBlock <ElementType> const m_table;
|
||||
};
|
||||
|
||||
explicit SharedTable (Data* data)
|
||||
: m_data (data)
|
||||
{
|
||||
}
|
||||
|
||||
SharedPtr <Data> m_data;
|
||||
};
|
||||
|
||||
template <class ElementType>
|
||||
SharedTable <ElementType> const SharedTable <ElementType>::null;
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SORTEDLOOKUPTABLE_H_INCLUDED
|
||||
#define BEAST_SORTEDLOOKUPTABLE_H_INCLUDED
|
||||
|
||||
/** Sorted map for fast lookups.
|
||||
|
||||
This container is optimized for a data set with fixed elements.
|
||||
|
||||
SchemaType obeys this concept:
|
||||
|
||||
@code
|
||||
|
||||
struct SchemaType
|
||||
{
|
||||
typename KeyType;
|
||||
typename ValueType;
|
||||
|
||||
// Retrieve the key for a specified value.
|
||||
KeyType getKey (Value const& value);
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
To use the table, reserve space with reserveSpaceForValues() if the number
|
||||
of elements is known ahead of time. Then, call insert() for all the your
|
||||
elements. Call prepareForLookups() once then call lookupValueByKey ()
|
||||
*/
|
||||
template <class SchemaType>
|
||||
class SortedLookupTable
|
||||
{
|
||||
private:
|
||||
typedef typename SchemaType::KeyType KeyType;
|
||||
typedef typename SchemaType::ValueType ValueType;
|
||||
typedef std::vector <ValueType> values_t;
|
||||
|
||||
private:
|
||||
struct SortCompare
|
||||
{
|
||||
bool operator () (ValueType const& lhs, ValueType const& rhs) const
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < SchemaType ().getKey (rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct FindCompare
|
||||
{
|
||||
bool operator () (ValueType const& lhs, ValueType const& rhs)
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < SchemaType ().getKey (rhs);
|
||||
}
|
||||
|
||||
bool operator () (KeyType const& key, ValueType const& rhs)
|
||||
{
|
||||
return key < SchemaType ().getKey (rhs);
|
||||
}
|
||||
|
||||
bool operator () (ValueType const& lhs, KeyType const& key)
|
||||
{
|
||||
return SchemaType ().getKey (lhs) < key;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename values_t::size_type size_type;
|
||||
|
||||
/** Reserve space for values.
|
||||
|
||||
Although not necessary, this can help with memory usage if the
|
||||
number of values is known ahead of time.
|
||||
|
||||
@param numberOfValues The amount of space to reserve.
|
||||
*/
|
||||
void reserveSpaceForValues (size_type numberOfValues)
|
||||
{
|
||||
m_values.reserve (numberOfValues);
|
||||
}
|
||||
|
||||
/** Insert a value into the index.
|
||||
|
||||
@invariant The value must not already exist in the index.
|
||||
|
||||
@param valueToInsert The value to insert.
|
||||
*/
|
||||
void insert (ValueType const& valueToInsert)
|
||||
{
|
||||
m_values.push_back (valueToInsert);
|
||||
}
|
||||
|
||||
/** Prepare the index for lookups.
|
||||
|
||||
This must be called at least once after calling insert()
|
||||
and before calling find().
|
||||
*/
|
||||
void prepareForLookups ()
|
||||
{
|
||||
std::sort (m_values.begin (), m_values.end (), SortCompare ());
|
||||
}
|
||||
|
||||
/** Find the value for a key.
|
||||
|
||||
Quickly locates a value matching the key, or returns false
|
||||
indicating no value was found.
|
||||
|
||||
@invariant You must call prepareForLookups() once, after all
|
||||
insertions, before calling this function.
|
||||
|
||||
@param key The key to locate.
|
||||
@param pFoundValue Pointer to store the value if a matching
|
||||
key was found.
|
||||
@return `true` if the value was found.
|
||||
*/
|
||||
bool lookupValueByKey (KeyType const& key, ValueType* pFoundValue)
|
||||
{
|
||||
bool found;
|
||||
|
||||
std::pair <typename values_t::iterator, typename values_t::iterator> result =
|
||||
std::equal_range (m_values.begin (), m_values.end (), key, FindCompare ());
|
||||
|
||||
if (result.first != result.second)
|
||||
{
|
||||
*pFoundValue = *result.first;
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private:
|
||||
values_t m_values;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
typedef value_type* iterator;
|
||||
typedef value_type const* const_iterator;
|
||||
|
||||
/** Hardened hash function for use with HashMap.
|
||||
/** Hardened hash function for use with hash based containers.
|
||||
The seed is used to make the hash unpredictable. This prevents
|
||||
attackers from exploiting crafted inputs to produce degenerate
|
||||
containers.
|
||||
@@ -59,21 +59,21 @@ public:
|
||||
will be generated from the system
|
||||
@param seedToUse An optional seed to use.
|
||||
*/
|
||||
explicit hasher (HashValue seedToUse = Random::getSystemRandom ().nextInt ())
|
||||
explicit hasher (std::size_t seedToUse = Random::getSystemRandom ().nextInt ())
|
||||
: m_seed (seedToUse)
|
||||
{
|
||||
}
|
||||
|
||||
/** Generates a simple hash from an UnsignedInteger. */
|
||||
HashValue operator() (UnsignedInteger const& key) const
|
||||
std::size_t operator() (UnsignedInteger const& key) const
|
||||
{
|
||||
HashValue hash;
|
||||
std::size_t hash;
|
||||
Murmur::Hash (key.cbegin (), key.size, m_seed, &hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
private:
|
||||
HashValue m_seed;
|
||||
std::size_t m_seed;
|
||||
};
|
||||
|
||||
/** Determins if two UnsignedInteger objects are equal. */
|
||||
|
||||
Reference in New Issue
Block a user