diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
index 987fad04b..9082fd54f 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj
@@ -110,9 +110,12 @@
-
+
+
+
+
-
+
@@ -124,7 +127,9 @@
+
+
@@ -450,6 +455,18 @@
true
true
+
+ true
+ true
+ 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 edf760bb1..2a04302ff 100644
--- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -161,6 +161,9 @@
{bf498396-2e1f-4903-be68-3053ba439af5}
+
+ {08ec13ba-4058-4ad7-afbb-cbb1c6e2fc4a}
+
@@ -181,9 +184,6 @@
beast_core\containers
-
- beast_core\containers
-
beast_core\containers
@@ -485,9 +485,6 @@
beast_core\zip\zlib
-
- beast_core\containers
-
beast_core\memory
@@ -920,6 +917,24 @@
beast_core\system
+
+ beast_core\containers
+
+
+ beast_core\containers
+
+
+ beast_core\containers
+
+
+ beast_core\containers
+
+
+ beast_core\containers\detail
+
+
+ beast_core\containers\detail
+
@@ -1399,6 +1414,12 @@
beast_core\system
+
+ 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 2aa4a0c9e..82944cfda 100644
--- a/Subtrees/beast/modules/beast_core/beast_core.cpp
+++ b/Subtrees/beast/modules/beast_core/beast_core.cpp
@@ -143,6 +143,8 @@ namespace beast
#include "containers/beast_NamedValueSet.cpp"
#include "containers/beast_PropertySet.cpp"
#include "containers/beast_Variant.cpp"
+#include "containers/DynamicArray.cpp"
+#include "containers/DynamicList.cpp"
#include "diagnostic/beast_Debug.cpp"
#include "diagnostic/beast_Error.cpp"
diff --git a/Subtrees/beast/modules/beast_core/beast_core.h b/Subtrees/beast/modules/beast_core/beast_core.h
index 895ae4cc1..2ac12c9fd 100644
--- a/Subtrees/beast/modules/beast_core/beast_core.h
+++ b/Subtrees/beast/modules/beast_core/beast_core.h
@@ -256,6 +256,9 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
# pragma warning (pop)
#endif
+# include "containers/detail/removecv.h"
+#include "containers/detail/copyconst.h"
+
#include "system/PlatformDefs.h"
#include "system/TargetPlatform.h"
#include "diagnostic/beast_Throw.h"
@@ -264,7 +267,7 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
#include "memory/beast_AtomicFlag.h"
#include "memory/beast_AtomicPointer.h"
#include "memory/beast_AtomicState.h"
-#include "containers/beast_List.h"
+#include "containers/List.h"
#include "containers/beast_LockFreeStack.h"
#include "threads/beast_SpinDelay.h"
#include "memory/beast_StaticObject.h"
@@ -301,7 +304,6 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
#include "containers/beast_DynamicObject.h"
#include "containers/beast_ElementComparator.h"
#include "maths/beast_Random.h"
-#include "containers/beast_HashMap.h"
#include "containers/beast_LinkedListPointer.h"
#include "containers/beast_LockFreeQueue.h"
#include "containers/beast_NamedValueSet.h"
@@ -315,6 +317,9 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
#include "maths/beast_Range.h"
#include "containers/beast_SparseSet.h"
#include "containers/beast_Variant.h"
+# include "containers/DynamicList.h"
+# include "containers/DynamicArray.h"
+#include "containers/HashMap.h"
#include "files/beast_DirectoryIterator.h"
#include "files/beast_File.h"
#include "files/beast_FileInputStream.h"
diff --git a/Subtrees/beast/modules/beast_core/containers/DynamicArray.cpp b/Subtrees/beast/modules/beast_core/containers/DynamicArray.cpp
new file mode 100644
index 000000000..1221e5084
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/DynamicArray.cpp
@@ -0,0 +1,171 @@
+//------------------------------------------------------------------------------
+/*
+ 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 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 (numberToAssign) << ")";
+ beginTestCase (s);
+
+ DynamicArray v;
+ v.assign (numberToAssign);
+
+ pass ();
+ }
+
+ void testReserve ()
+ {
+ String s;
+ s << "reserve (" << String::fromNumber (numberToReserve) << ")";
+ beginTestCase (s);
+
+ DynamicArray v;
+ v.reserve (numberToReserve);
+
+ v.assign (numberToReserve);
+
+ pass ();
+ }
+
+ void testMutate ()
+ {
+ String s;
+ DynamicArray v;
+
+ s = "push_back (" + String::fromNumber (numberToMutate) + ")";
+ beginTestCase (s);
+ for (std::size_t i = 0; i < numberToMutate; ++i)
+ v.push_back (T (String::fromNumber (i)));
+
+ s = "read [] (" + String::fromNumber (numberToMutate) + ")";
+ beginTestCase (s);
+ for (std::size_t i = 0; i < numberToMutate; ++i)
+ expect (v [i].msg == String::fromNumber (i));
+
+ s = "write [] (" + String::fromNumber (numberToMutate) + ")";
+ beginTestCase (s);
+ for (std::size_t i = 0; i < numberToMutate; ++i)
+ v [i].msg = "+" + String::fromNumber (i);
+
+ s = "verify [] (" + String::fromNumber (numberToMutate) + ")";
+ beginTestCase (s);
+ for (std::size_t i = 0; i < numberToMutate; ++i)
+ expect (v [i].msg == String ("+") + String::fromNumber (i));
+ }
+
+ void testIterate ()
+ {
+ typedef DynamicArray 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 ();
+ }
+ }
+
+ {
+ 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 ();
+ }
+ }
+ }
+
+ void runTest ()
+ {
+ testAssign ();
+ testReserve ();
+ testMutate ();
+ testIterate ();
+ }
+
+ DynamicArrayTests () : UnitTest ("DynamicArray", "beast")
+ {
+ }
+};
+
+static DynamicArrayTests dynamicArrayTests;
diff --git a/Subtrees/beast/modules/beast_core/containers/DynamicArray.h b/Subtrees/beast/modules/beast_core/containers/DynamicArray.h
new file mode 100644
index 000000000..70a079cae
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/DynamicArray.h
@@ -0,0 +1,728 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#ifndef BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED
+#define BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED
+
+template
+class DynamicArray;
+
+namespace detail
+{
+
+template
+class DynamicArrayIterator
+ : public std::iterator
+{
+public:
+ typedef typename copyconst ::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
+ DynamicArrayIterator (DynamicArrayIterator const& u) noexcept
+ : m_v (u.m_v)
+ , m_pos (u.m_pos)
+ {
+ }
+
+ template
+ DynamicArrayIterator& operator= (DynamicArrayIterator const& u) noexcept
+ {
+ m_v = u.m_v;
+ m_pos = u.m_pos;
+ return *this;
+ }
+
+ template
+ bool operator== (DynamicArrayIterator const& u) const noexcept
+ {
+ return (m_v == u.m_v) && (m_pos == u.m_pos);
+ }
+
+ template
+ bool operator!= (DynamicArrayIterator 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
+ difference_type operator- (DynamicArrayIterator const& rhs) const noexcept
+ {
+ return m_pos - rhs.m_pos;
+ }
+
+ template
+ bool operator< (DynamicArrayIterator const& rhs) const noexcept
+ {
+ return m_pos < rhs.m_pos;
+ }
+
+ template
+ bool operator> (DynamicArrayIterator const& rhs) const noexcept
+ {
+ return m_pos > rhs.m_pos;
+ }
+
+ template
+ bool operator<= (DynamicArrayIterator const& rhs) const noexcept
+ {
+ return m_pos <= rhs.m_pos;
+ }
+
+ template
+ bool operator>= (DynamicArrayIterator 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
+ friend class DynamicArrayIterator;
+
+ V* m_v;
+ size_type m_pos;
+};
+
+//------------------------------------------------------------------------------
+
+template
+DynamicArrayIterator operator+ (
+ typename DynamicArrayIterator ::difference_type n,
+ DynamicArrayIterator iter) noexcept
+{
+ return iter + n;
+}
+
+template
+DynamicArrayIterator operator- (
+ typename DynamicArrayIterator ::difference_type n,
+ DynamicArrayIterator iter) noexcept
+{
+ return iter - n;
+}
+
+//------------------------------------------------------------------------------
+
+template
+class DynamicArrayReverseIterator
+ : public std::iterator
+{
+public:
+ typedef typename copyconst ::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
+ DynamicArrayReverseIterator (DynamicArrayReverseIterator const& u) noexcept
+ : m_v (u.m_v)
+ , m_pos (u.m_pos)
+ {
+ }
+
+ template
+ DynamicArrayReverseIterator& operator= (DynamicArrayReverseIterator const& u) noexcept
+ {
+ m_v = u.m_v;
+ m_pos = u.m_pos;
+ return *this;
+ }
+
+ template
+ bool operator== (DynamicArrayReverseIterator const& u) const noexcept
+ {
+ return (m_v == u.m_v) && (m_pos == u.m_pos);
+ }
+
+ template
+ bool operator!= (DynamicArrayReverseIterator 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
+ difference_type operator- (DynamicArrayReverseIterator const& rhs) const noexcept
+ {
+ return rhs.m_pos - m_pos;
+ }
+
+ template
+ bool operator< (DynamicArrayReverseIterator const& rhs) const noexcept
+ {
+ return m_pos > rhs.m_pos;
+ }
+
+ template
+ bool operator> (DynamicArrayReverseIterator const& rhs) const noexcept
+ {
+ return m_pos < rhs.m_pos;
+ }
+
+ template
+ bool operator<= (DynamicArrayReverseIterator const& rhs) const noexcept
+ {
+ return m_pos >= rhs.m_pos;
+ }
+
+ template
+ bool operator>= (DynamicArrayReverseIterator 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
+ 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
+DynamicArrayReverseIterator operator+ (
+ typename DynamicArrayReverseIterator ::difference_type n,
+ DynamicArrayReverseIterator iter) noexcept
+{
+ return iter + n;
+}
+
+template
+DynamicArrayReverseIterator operator- (
+ typename DynamicArrayReverseIterator ::difference_type n,
+ DynamicArrayReverseIterator iter) noexcept
+{
+ return iter - n;
+}
+
+}
+
+//------------------------------------------------------------------------------
+
+template >
+class DynamicArray
+{
+private:
+ typedef PARAMETER_TYPE (T) TParam;
+
+ typedef std::vector 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 > iterator;
+
+ typedef detail::DynamicArrayIterator const> const_iterator;
+
+ typedef detail::DynamicArrayReverseIterator > reverse_iterator;
+
+ typedef detail::DynamicArrayReverseIterator 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 ::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 (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
+ iterator emplace_back (A1 a1)
+ {
+ ::new (alloc ()) T (a1);
+ return iterator (this, size () - 1);
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2)
+ {
+ ::new (alloc ()) T (a1, a2);
+ return iterator (this, size () - 1);
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2, A3 a3)
+ {
+ ::new (alloc ()) T (a1, a2, a3);
+ return iterator (this, size () - 1);
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ ::new (alloc ()) T (a1, a2, a3, a4);
+ return iterator (this, size () - 1);
+ }
+
+ template
+ 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
diff --git a/Subtrees/beast/modules/beast_core/containers/DynamicList.cpp b/Subtrees/beast/modules/beast_core/containers/DynamicList.cpp
new file mode 100644
index 000000000..e32a065f4
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/DynamicList.cpp
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+/*
+ 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 DynamicListTests : 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 (numberToAssign) << ")";
+ beginTestCase (s);
+
+ pass ();
+ }
+
+ void runTest ()
+ {
+ testAssign ();
+ }
+
+ DynamicListTests () : UnitTest ("DynamicList", "beast")
+ {
+ }
+};
+
+static DynamicListTests DynamicListTests;
diff --git a/Subtrees/beast/modules/beast_core/containers/DynamicList.h b/Subtrees/beast/modules/beast_core/containers/DynamicList.h
new file mode 100644
index 000000000..9ccbda4dd
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/DynamicList.h
@@ -0,0 +1,452 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#ifndef BEAST_CORE_CONTAINERS_DYNAMICLIST_H_INCLUDED
+#define BEAST_CORE_CONTAINERS_DYNAMICLIST_H_INCLUDED
+
+template
+class DynamicList;
+
+namespace detail
+{
+
+template
+class DynamicListIterator
+ : public std::iterator
+{
+public:
+ typedef typename I::value_type ItemType; // this will be -
+ typedef typename ItemType::value_type T; // this is the original T
+
+ typedef typename copyconst ::type
+
+ value_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef typename I::size_type size_type;
+
+ DynamicListIterator (I iter = I ()) noexcept
+ : m_iter (iter)
+ {
+ }
+
+#if 1
+ template
+ DynamicListIterator (DynamicListIterator const& other) noexcept
+ : m_iter (other.m_iter)
+ {
+ }
+
+ template
+ DynamicListIterator& operator= (DynamicListIterator const& other) noexcept
+ {
+ m_iter = other.m_iter;
+ return *this;
+ }
+#endif
+
+ template
+ bool operator== (DynamicListIterator const& other) const noexcept
+ {
+ return m_iter == other.m_iter;
+ }
+
+ template
+ bool operator != (DynamicListIterator const& other) const noexcept
+ {
+ return ! this->operator== (other);
+ }
+
+ reference operator* () const noexcept
+ {
+ return dereference ();
+ }
+
+ pointer operator-> () const noexcept
+ {
+ return &dereference ();
+ }
+
+ DynamicListIterator& operator++ () noexcept
+ {
+ increment ();
+ return *this;
+ }
+
+ DynamicListIterator operator++ (int) noexcept
+ {
+ DynamicListIterator const result (*this);
+ increment ();
+ return result;
+ }
+
+ DynamicListIterator& operator-- () noexcept
+ {
+ decrement ();
+ return *this;
+ }
+
+ DynamicListIterator operator-- (int) noexcept
+ {
+ DynamicListIterator const result (*this);
+ decrement ();
+ return result;
+ }
+
+private:
+ template
+ friend class DynamicList;
+
+ typedef typename I::value_type Item;
+
+ reference dereference () const noexcept
+ {
+ return *(m_iter->get ());
+ }
+
+ void increment () noexcept
+ {
+ ++m_iter;
+ }
+
+ void decrement () noexcept
+ {
+ --m_iter;
+ }
+
+ I m_iter;
+};
+
+}
+
+//------------------------------------------------------------------------------
+
+/** A list that uses a very small number of dynamic allocations.
+
+ Once an element is allocated, its address does not change. Elements
+ can be erased, and they are placed onto a deleted list for re-use.
+ Allocations occur in configurable batches.
+
+ Iterators to elements never become invalid, they can be safely
+ stored elsewhere, as long as the underlying element is not erased.
+
+ T may support these concepts:
+ DefaultConstructible
+ MoveConstructible (C++11)
+
+ T must support these concepts:
+ Destructible
+*/
+template >
+class DynamicList
+{
+private:
+ typedef PARAMETER_TYPE (T) TParam;
+
+public:
+ enum
+ {
+ defaultBlocksize = 1000
+ };
+
+ typedef T value_type;
+ typedef Allocator allocator_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef T const* const_pointer;
+ typedef T const& const_reference;
+
+private:
+ struct Item : List
- ::Node
+ {
+ typedef T value_type;
+
+ T* get () noexcept
+ {
+ return reinterpret_cast (&storage [0]);
+ }
+
+ T const* get () const noexcept
+ {
+ return reinterpret_cast (&storage [0]);
+ }
+
+ private:
+ // Lets hope this is padded correctly
+ uint8 storage [sizeof (T)];
+ };
+
+public:
+ typedef detail::DynamicListIterator <
+ typename List
- ::iterator> iterator;
+
+ typedef detail::DynamicListIterator <
+ typename List
- ::const_iterator> const_iterator;
+
+ explicit DynamicList (
+ size_type blocksize = defaultBlocksize,
+ Allocator const& allocator = Allocator ())
+ : m_allocator (allocator)
+ , m_blocksize (blocksize)
+ , m_capacity (0)
+ {
+ }
+
+ ~DynamicList ()
+ {
+ clear ();
+ shrink_to_fit ();
+ }
+
+ allocator_type get_allocator () const noexcept
+ {
+ return m_allocator;
+ }
+
+ //--------------------------------------------------------------------------
+
+ reference front () noexcept
+ {
+ return *m_items.front ().get ();
+ }
+
+ const_reference front () const noexcept
+ {
+ return *m_items.front ().get ();
+ }
+
+ reference back () noexcept
+ {
+ return *m_items.back ().get ();
+ }
+
+ const_reference back () const noexcept
+ {
+ return *m_items.back ().get ();
+ }
+
+ //--------------------------------------------------------------------------
+
+ iterator begin () noexcept
+ {
+ return iterator (m_items.begin ());
+ }
+
+ const_iterator begin () const noexcept
+ {
+ return const_iterator (m_items.begin ());
+ }
+
+ const_iterator cbegin () const noexcept
+ {
+ return const_iterator (m_items.cbegin ());
+ }
+
+ iterator end () noexcept
+ {
+ return iterator (m_items.end ());
+ }
+
+ const_iterator end () const noexcept
+ {
+ return const_iterator (m_items.end ());
+ }
+
+ const_iterator cend () const noexcept
+ {
+ return const_iterator (m_items.cend ());
+ }
+
+ iterator iterator_to (T& value) noexcept
+ {
+ std::ptrdiff_t const offset (
+ (std::ptrdiff_t)(((Item const*)0)->get ()));
+ Item& item (*addBytesToPointer (((Item*)&value), -offset));
+ return iterator (m_items.iterator_to (item));
+ }
+
+ const_iterator const_iterator_to (T const& value) const noexcept
+ {
+ std::ptrdiff_t const offset (
+ (std::ptrdiff_t)(((Item const*)0)->get ()));
+ Item const& item (*addBytesToPointer (((Item const*)&value), -offset));
+ return const_iterator (m_items.const_iterator_to (item));
+ }
+
+ //--------------------------------------------------------------------------
+
+ bool empty () const noexcept
+ {
+ return m_items.empty ();
+ }
+
+ size_type size () const noexcept
+ {
+ return m_items.size ();
+ }
+
+ size_type max_size () const noexcept
+ {
+ return std::numeric_limits ::max ();
+ }
+
+ void reserve (size_type new_cap) noexcept
+ {
+ 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
- (std::malloc (
+ m_blocksize * sizeof (Item))));
+ m_capacity = new_cap;
+ }
+
+ size_type capacity () const noexcept
+ {
+ return m_capacity;
+ }
+
+ void shrink_to_fit ()
+ {
+ // Special case when all allocated
+ // items are part of the free list.
+ if (m_items.empty ())
+ m_free.clear ();
+
+ size_type const used (m_items.size () + m_free.size ());
+ size_type const handles ((used + 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 ()
+ {
+ // Might want to skip this if is_pod is true
+ for (typename List
- ::iterator iter = m_items.begin ();
+ iter != m_items.end ();)
+ {
+ Item& item (*iter++);
+ item.get ()->~T ();
+ m_free.push_back (item);
+ }
+ }
+
+ /** Allocate a new default-constructed element and return the iterator.
+ If there are deleted elements in the free list, the new element
+ may not be created at the end of the storage area.
+ */
+ iterator emplace_back ()
+ {
+ return iterator_to (*::new (alloc ()->get ()) T ());
+ }
+
+ template
+ iterator emplace_back (A1 a1)
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (a1));
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2)
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (a1, a2));
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2, A3 a3)
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (a1, a2, a3));
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4)
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (a1, a2, a3, a4));
+ }
+
+ template
+ iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (a1, a2, a3, a4, a5));
+ }
+
+ /** Allocate a new copy-constructed element and return the index. */
+ iterator push_back (TParam value) noexcept
+ {
+ return iterator_to (*::new (alloc ()->get ()) T (value));
+ }
+
+ /** Erase the element at the specified position. */
+ iterator erase (iterator pos)
+ {
+ Item& item (*pos.m_iter);
+ item.get ()->~T ();
+ pos = m_items.erase (m_items.iterator_to (item));
+ m_free.push_front (item);
+ return pos;
+ }
+
+private:
+ Item* alloc () noexcept
+ {
+ Item* item;
+ if (m_free.empty ())
+ {
+ if (m_capacity <= m_items.size ())
+ reserve (m_items.size () + 1);
+
+ size_type const index (m_items.size () / m_blocksize);
+ size_type const offset (m_items.size () - index * m_blocksize);
+ item = m_handles [index] + offset;
+ }
+ else
+ {
+ item = &m_free.pop_front ();
+ }
+
+ m_items.push_back (*item);
+ return item;
+ }
+
+ typedef std::vector
- blocks_t;
+
+ Allocator m_allocator;
+ size_type m_blocksize;
+ size_type m_capacity;
+ std::vector
- m_handles;
+ List
- m_items;
+ List
- m_free;
+};
+
+#endif
diff --git a/Subtrees/beast/modules/beast_core/containers/HashMap.h b/Subtrees/beast/modules/beast_core/containers/HashMap.h
new file mode 100644
index 000000000..3cfb17fcb
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/HashMap.h
@@ -0,0 +1,833 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ 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
+{
+
+template
+class HashMapLocalIterator
+ : public std::iterator
+{
+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
+ HashMapLocalIterator (HashMapLocalIterator const& other)
+ : m_map (other.m_map)
+ , m_iter (other.m_iter)
+ {
+ }
+
+ template
+ HashMapLocalIterator& operator= (HashMapLocalIterator const& other)
+ {
+ m_map = other.m_map;
+ m_iter = other.m_iter;
+ return *this;
+ }
+
+ template
+ bool operator== (HashMapLocalIterator const& other)
+ {
+ return m_map == other.m_map && m_iter == other.m_iter;
+ }
+
+ template
+ bool operator!= (HashMapLocalIterator 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
+class HashMapIterator
+ : public std::iterator
+{
+private:
+ typedef typename M::Item Item;
+ typedef typename M::Bucket Bucket;
+ typedef detail::ListIterator ::Node>::type> bucket_iterator;
+ typedef detail::ListIterator ::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,
+ bucket_iterator bucket = bucket_iterator (),
+ item_iterator local = item_iterator ())
+ : m_map (map)
+ , m_bucket (bucket)
+ , m_local (local)
+ {
+ }
+
+ template
+ HashMapIterator (HashMapIterator const& other) noexcept
+ : m_map (other.m_map)
+ , m_bucket (other.m_bucket)
+ , m_local (other.m_local)
+ {
+ }
+
+ template
+ HashMapIterator& operator= (HashMapIterator const& other) noexcept
+ {
+ m_map = other.m_map;
+ m_bucket = other.m_bucket;
+ m_local = other.m_local;
+ return *this;
+ }
+
+ template
+ bool operator== (HashMapIterator const& other) noexcept
+ {
+ return m_map == other.m_map &&
+ m_bucket == other.m_bucket &&
+ m_local == other.m_local;
+ }
+
+ template
+ bool operator!= (HashMapIterator 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
+ 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 Allocator = std::allocator >
+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
+ friend class detail::HashMapLocalIterator;
+
+ class Item;
+
+ // Each non-empty bucket is in the linked list.
+ struct Bucket : List ::Node
+ {
+ Bucket ()
+ {
+ }
+
+ inline bool empty () const noexcept
+ {
+ return items.empty ();
+ }
+
+ List
- items;
+
+ private:
+ Bucket& operator= (Bucket const&);
+ Bucket (Bucket const&);
+ };
+
+ // Every item in the map is in one linked list
+ struct Item
+ : List
- ::Node
+ , List
- ::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 detail::HashMapIterator > iterator;
+ typedef detail::HashMapIterator const> const_iterator;
+
+ typedef detail::HashMapLocalIterator <
+ HashMap ,
+ typename List
- ::iterator> local_iterator;
+
+ typedef detail::HashMapLocalIterator <
+ HashMap const,
+ typename List
- ::const_iterator> const_local_iterator;
+
+ //--------------------------------------------------------------------------
+
+ enum
+ {
+ initialBucketCount = 101,
+ percentageIncrease = 75
+ };
+
+ 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 (this, m_bucketlist.end ());
+ }
+
+ const_iterator end () const noexcept
+ {
+ return const_iterator (this, m_bucketlist.end ());
+ }
+
+ const_iterator cend () const noexcept
+ {
+ return const_iterator (this, m_bucketlist.cend ());
+ }
+
+ //--------------------------------------------------------------------------
+
+ 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 ::max ();
+ }
+
+ //--------------------------------------------------------------------------
+
+ void clear()
+ {
+ for (typename DynamicList
- ::iterator iter = m_items.begin ();
+ iter != m_items.end ();)
+ {
+ typename DynamicList
- ::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
- ::iterator iter (b.items.begin ());
+ iter != b.items.end ();)
+ {
+ typename List
- ::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
- ::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 ::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
- ::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 ()
+ {
+ float const scale = 1.f + (float (percentageIncrease) / 100.f);
+ size_type const count (std::ceil (
+ (size () / max_load_factor ()) * scale));
+ rehash (count);
+ }
+
+ iterator find (KeyParam key, size_type n) noexcept
+ {
+ Bucket& b (m_buckets [n]);
+ 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);
+ return end ();
+ }
+
+ const_iterator find (KeyParam key, size_type n) const noexcept
+ {
+ Bucket const& b (m_buckets [n]);
+ 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,
+ 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
- ::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
+ friend class detail::HashMapIterator;
+
+ Hash m_hash;
+ KeyEqual m_equal;
+ Allocator m_allocator;
+ DynamicList
- m_items;
+ DynamicArray m_buckets;
+ List
- m_itemlist;
+ List m_bucketlist;
+ float m_max_load_factor;
+};
+
+#endif
+
diff --git a/Subtrees/beast/modules/beast_core/containers/beast_List.h b/Subtrees/beast/modules/beast_core/containers/List.h
similarity index 70%
rename from Subtrees/beast/modules/beast_core/containers/beast_List.h
rename to Subtrees/beast/modules/beast_core/containers/List.h
index c187579b9..0d96e61d4 100644
--- a/Subtrees/beast/modules/beast_core/containers/beast_List.h
+++ b/Subtrees/beast/modules/beast_core/containers/List.h
@@ -17,8 +17,8 @@
*/
//==============================================================================
-#ifndef BEAST_LIST_H_INCLUDED
-#define BEAST_LIST_H_INCLUDED
+#ifndef BEAST_CORE_CONTAINERS_LIST_H_INCLUDED
+#define BEAST_CORE_CONTAINERS_LIST_H_INCLUDED
/** Intrusive Containers
@@ -189,14 +189,138 @@
@defgroup intrusive intrusive
@ingroup beast_core
*/
+
+//------------------------------------------------------------------------------
+
+template
+class List;
+
+namespace detail
+{
+
+// This is the intrusive portion of the doubly linked list.
+// One derivation per list that the object may appear on
+// concurrently is required.
+//
+template
+class ListNode : public Uncopyable
+{
+private:
+ typedef T value_type;
+
+ template
+ friend class List;
+
+ template
+ friend class ListIterator;
+
+ ListNode* m_next;
+ ListNode* m_prev;
+};
//------------------------------------------------------------------------------
-/** Default tag for List.
+template
+class ListIterator : public std::iterator <
+ std::bidirectional_iterator_tag, std::size_t>
+{
+public:
+ typedef typename copyconst ::type
+
+ value_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef std::size_t size_type;
- @ingroup beast_core intrusive
-*/
-struct ListDefaultTag;
+ ListIterator (N* node = nullptr) noexcept
+ : m_node (node)
+ {
+ }
+#if 0
+ template
+ ListIterator (ListIterator const& other) noexcept
+ : m_node (other.m_node)
+ {
+ }
+
+ template
+ ListIterator& operator= (ListIterator const& other) noexcept
+ {
+ m_node = other.m_node;
+ return *this;
+ }
+#endif
+ template
+ bool operator== (ListIterator const& other) const noexcept
+ {
+ return m_node == other.m_node;
+ }
+
+ template
+ bool operator!= (ListIterator const& other) const noexcept
+ {
+ return ! ((*this) == other);
+ }
+
+ reference operator* () const noexcept
+ {
+ return dereference ();
+ }
+
+ pointer operator-> () const noexcept
+ {
+ return &dereference ();
+ }
+
+ ListIterator& operator++ () noexcept
+ {
+ increment ();
+ return *this;
+ }
+
+ ListIterator operator++ (int) noexcept
+ {
+ ListIterator result (*this);
+ increment ();
+ return result;
+ }
+
+ ListIterator& operator-- () noexcept
+ {
+ decrement ();
+ return *this;
+ }
+
+ ListIterator operator-- (int) noexcept
+ {
+ ListIterator result (*this);
+ decrement ();
+ return result;
+ }
+
+private:
+ reference dereference () const noexcept
+ {
+ return static_cast (*m_node);
+ }
+
+ void increment () noexcept
+ {
+ bassert (m_node->m_next);
+ m_node = m_node->m_next;
+ }
+
+ void decrement () noexcept
+ {
+ bassert (m_node->m_prev &&
+ m_node->m_prev->m_prev != nullptr);
+ m_node = m_node->m_prev;
+ }
+
+ N* m_node;
+};
+
+}
/**
Intrusive doubly linked list.
@@ -295,7 +419,7 @@ struct ListDefaultTag;
@endcode
- @tparam Element The base type of element which the list will store
+ @tparam T The base type of element which the list will store
pointers to.
@tparam Tag An optional unique type name used to distinguish lists and nodes,
@@ -303,300 +427,133 @@ struct ListDefaultTag;
@ingroup beast_core intrusive
*/
-template
+template
class List : public Uncopyable
{
public:
- typedef int size_type;
+ typedef typename detail::ListNode Node;
- typedef Element value_type;
- typedef Element& reference;
- typedef Element const& const_reference;
- typedef Element* pointer;
- typedef Element const* const_pointer;
+ typedef T value_type;
+ typedef value_type* pointer;
+ typedef value_type& reference;
+ typedef value_type const* const_pointer;
+ typedef value_type const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
- /** Thrown when some members are called with an empty list. */
- struct empty_list_error : std::logic_error
- {
- empty_list_error () : std::logic_error ("empty list")
- {
- }
- };
+ typedef detail::ListIterator iterator;
+ typedef detail::ListIterator const_iterator;
- class Node : public Uncopyable
- {
- public:
- Node () { }
-
- private:
- friend class List;
- Node* m_next;
- Node* m_prev;
- };
-
-private:
- template
- class iterator_base : public std::iterator <
- std::bidirectional_iterator_tag, int >
- {
- public:
- typedef ElemType value_type;
- typedef ElemType* pointer;
- typedef ElemType& reference;
-
- iterator_base (NodeType* node = nullptr) : m_node (node)
- {
- }
-
- template
- iterator_base (iterator_base const& other)
- : m_node (other.m_node)
- {
- }
-
- template
- iterator_base& operator= (iterator_base const& other)
- {
- m_node = other.m_node;
- return *this;
- }
-
- template
- bool operator == (iterator_base const& other) const
- {
- return m_node == other.m_node;
- }
-
- template
- bool operator != (iterator_base const& other) const
- {
- return ! this->operator== (other);
- }
-
- reference operator* () const
- {
- return dereference ();
- }
-
- pointer operator-> () const
- {
- return &dereference ();
- }
-
- iterator_base& operator++ ()
- {
- increment ();
- return *this;
- }
-
- iterator_base operator++ (int)
- {
- iterator_base result (*this);
- increment ();
- return result;
- }
-
- iterator_base& operator-- ()
- {
- decrement ();
- return *this;
- }
-
- iterator_base operator-- (int)
- {
- iterator_base result (*this);
- decrement ();
- return result;
- }
-
- private:
- friend class List;
-
- NodeType* get_node ()
- {
- return m_node;
- }
-
- NodeType const* get_node () const
- {
- return m_node;
- }
-
- reference dereference () const
- {
- return *static_cast (m_node);
- }
-
- bool equal (NodeType* const* node) const
- {
- return m_node == node;
- }
-
- void increment ()
- {
- bassert (m_node->m_next);
- m_node = m_node->m_next;
- }
-
- void decrement ()
- {
- bassert (m_node->m_prev && m_node->m_prev->m_prev != 0);
- m_node = m_node->m_prev;
- }
-
- private:
- NodeType* m_node;
- };
-
-public:
- /** A read/write List iterator. */
- typedef iterator_base iterator;
-
- /** A read-only List iterator. */
- typedef iterator_base const_iterator;
-
-public:
/** Create an empty list. */
- List () : m_size (0)
+ List ()
{
m_head.m_prev = nullptr; // identifies the head
m_tail.m_next = nullptr; // identifies the tail
clear ();
}
- /** Returns the number of elements in the list
-
- @return The number of elements in the list.
+ /** Determine if the list is empty.
+ @return `true` if the list is empty.
*/
- size_type size () const
+ bool empty () const noexcept
+ {
+ return size () == 0;
+ }
+
+ /** Returns the number of elements in the list. */
+ size_type size () const noexcept
{
return m_size;
}
/** Obtain a reference to the first element.
-
@invariant The list may not be empty.
-
@return A reference to the first element.
*/
- reference front ()
+ reference front () noexcept
{
- if (empty ())
- Throw (empty_list_error (), __FILE__, __LINE__);
-
return element_from (m_head.m_next);
}
/** Obtain a const reference to the first element.
-
@invariant The list may not be empty.
-
@return A const reference to the first element.
*/
- const_reference front () const
+ const_reference front () const noexcept
{
- if (empty ())
- Throw (empty_list_error (), __FILE__, __LINE__);
-
return element_from (m_head.m_next);
}
/** Obtain a reference to the last element.
-
@invariant The list may not be empty.
-
@return A reference to the last element.
*/
- reference back ()
+ reference back () noexcept
{
- if (empty ())
- Throw (empty_list_error (), __FILE__, __LINE__);
-
return element_from (m_tail.m_prev);
}
/** Obtain a const reference to the last element.
-
@invariant The list may not be empty.
-
@return A const reference to the last element.
*/
- const_reference back () const
+ const_reference back () const noexcept
{
- if (empty ())
- Throw (empty_list_error (), __FILE__, __LINE__);
-
return element_from (m_tail.m_prev);
}
/** Obtain an iterator to the beginning of the list.
-
@return An iterator pointing to the beginning of the list.
*/
- iterator begin ()
+ iterator begin () noexcept
{
return iterator (m_head.m_next);
}
/** Obtain a const iterator to the beginning of the list.
-
@return A const iterator pointing to the beginning of the list.
*/
- const_iterator begin () const
+ const_iterator begin () const noexcept
{
return const_iterator (m_head.m_next);
}
/** Obtain a const iterator to the beginning of the list.
-
@return A const iterator pointing to the beginning of the list.
*/
- const_iterator cbegin () const
+ const_iterator cbegin () const noexcept
{
return const_iterator (m_head.m_next);
}
/** Obtain a iterator to the end of the list.
-
@return An iterator pointing to the end of the list.
*/
- iterator end ()
+ iterator end () noexcept
{
return iterator (&m_tail);
}
/** Obtain a const iterator to the end of the list.
-
@return A constiterator pointing to the end of the list.
*/
- const_iterator end () const
+ const_iterator end () const noexcept
{
return const_iterator (&m_tail);
}
- /** Obtain a const iterator to the end of the list.
-
+ /** Obtain a const iterator to the end of the list
@return A constiterator pointing to the end of the list.
*/
- const_iterator cend () const
+ const_iterator cend () const noexcept
{
return const_iterator (&m_tail);
}
- /** Determine if the list is empty.
-
- @return `true` if the list is empty.
- */
- bool empty () const
- {
- return m_head.m_next == &m_tail;
- }
-
/** Clear the list.
-
@note This does not free the elements.
*/
- void clear ()
+ void clear () noexcept
{
m_head.m_next = &m_tail;
m_tail.m_prev = &m_head;
@@ -604,19 +561,15 @@ public:
}
/** Insert an element.
-
@invariant The element must not already be in the list.
-
@param pos The location to insert after.
-
- @param elem The element to insert.
-
+ @param element The element to insert.
@return An iterator pointing to the newly inserted element.
*/
- iterator insert (iterator pos, Element& elem)
+ iterator insert (iterator pos, T& element) noexcept
{
- Node* node = node_from (elem);
- node->m_next = pos.get_node ();
+ Node* node = static_cast (&element);
+ node->m_next = &*pos;
node->m_prev = node->m_next->m_prev;
node->m_next->m_prev = node;
node->m_prev->m_next = node;
@@ -625,19 +578,16 @@ public:
}
/** Insert another list into this one.
-
The other list is cleared.
-
@param pos The location to insert after.
-
@param other The list to insert.
*/
- void insert (iterator pos, List& other)
+ void insert (iterator pos, List& other) noexcept
{
if (!other.empty ())
{
- Node* before = pos.get_node ();
+ Node* before = &*pos;
other.m_head.m_next->m_prev = before->m_prev;
before->m_prev->m_next = other.m_head.m_next;
other.m_tail.m_prev->m_next = before;
@@ -648,16 +598,13 @@ public:
}
/** Remove an element.
-
@invariant The element must exist in the list.
-
@param pos An iterator pointing to the element to remove.
-
@return An iterator pointing to the next element after the one removed.
*/
- iterator erase (iterator pos)
+ iterator erase (iterator pos) noexcept
{
- Node* node = pos.get_node ();
+ Node* node = &*pos;
++pos;
node->m_next->m_prev = node->m_prev;
node->m_prev->m_next = node->m_next;
@@ -666,54 +613,47 @@ public:
}
/** Insert an element at the beginning of the list.
-
@invariant The element must not exist in the list.
-
- @param elem The element to insert.
+ @param element The element to insert.
*/
- void push_front (Element& elem)
+ iterator push_front (T& element) noexcept
{
- insert (begin (), elem);
+ return insert (begin (), element);
}
/** Remove the element at the beginning of the list.
-
@invariant The list must not be empty.
@return A reference to the popped element.
*/
- Element& pop_front ()
+ T& pop_front () noexcept
{
- Element& elem (front ());
+ T& element (front ());
erase (begin ());
- return elem;
+ return element;
}
/** Append an element at the end of the list.
-
@invariant The element must not exist in the list.
-
- @param elem The element to append.
+ @param element The element to append.
*/
- void push_back (Element& elem)
+ iterator push_back (T& element) noexcept
{
- insert (end (), elem);
+ return insert (end (), element);
}
/** Remove the element at the end of the list.
-
@invariant The list must not be empty.
@return A reference to the popped element.
*/
- Element& pop_back ()
+ T& pop_back () noexcept
{
- Element& elem (back ());
+ T& element (back ());
erase (--end ());
- return elem;
+ return element;
}
- /** Swap contents with another list.
- */
- void swap (List& other)
+ /** Swap contents with another list. */
+ void swap (List& other) noexcept
{
List temp;
temp.append (other);
@@ -722,72 +662,52 @@ public:
}
/** Insert another list at the beginning of this list.
-
The other list is cleared.
-
@param list The other list to insert.
*/
- void prepend (List& list)
+ iterator prepend (List& list) noexcept
{
- insert (begin (), list);
+ return insert (begin (), list);
}
/** Append another list at the end of this list.
-
The other list is cleared.
-
@param list the other list to append.
*/
- void append (List& list)
+ iterator append (List& list) noexcept
{
- insert (end (), list);
+ return insert (end (), list);
}
/** Obtain an iterator from an element.
-
@invariant The element must exist in the list.
-
- @param elem The element to obtain an iterator for.
-
+ @param element The element to obtain an iterator for.
@return An iterator to the element.
*/
- iterator iterator_to (Element& elem) const
+ iterator iterator_to (T& element) const noexcept
{
- return iterator (static_cast (&elem));
+ return iterator (static_cast (&element));
}
/** Obtain a const iterator from an element.
-
@invariant The element must exist in the list.
-
- @param elem The element to obtain an iterator for.
-
+ @param element The element to obtain an iterator for.
@return A const iterator to the element.
*/
- const_iterator const_iterator_to (Element const& elem) const
+ const_iterator const_iterator_to (T const& element) const noexcept
{
- return const_iterator (static_cast (&elem));
+ return const_iterator (static_cast (&element));
}
private:
- inline reference element_from (Node* node)
+ reference element_from (Node* node) noexcept
{
- return * (static_cast (node));
+ return *(static_cast (node));
}
- inline const_reference element_from (Node const* node) const
+ const_reference element_from (Node const* node) const noexcept
{
- return * (static_cast (node));
- }
-
- inline Node* node_from (Element& elem)
- {
- return static_cast (&elem);
- }
-
- inline Node const* node_from (Element const& elem) const
- {
- return static_cast (&elem);
+ return *(static_cast (node));
}
private:
diff --git a/Subtrees/beast/modules/beast_core/containers/beast_HashMap.h b/Subtrees/beast/modules/beast_core/containers/beast_HashMap.h
deleted file mode 100644
index 75eebdbfa..000000000
--- a/Subtrees/beast/modules/beast_core/containers/beast_HashMap.h
+++ /dev/null
@@ -1,487 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of Beast: https://github.com/vinniefalco/Beast
- Copyright 2013, Vinnie Falco
-
- 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
-
-#include "beast_OwnedArray.h"
-#include "beast_LinkedListPointer.h"
-#include "../memory/beast_ScopedPointer.h"
-
-/** 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. */
- int generateHash (const int key, const int upperLimit) const noexcept { return std::abs (key) % upperLimit; }
- /** Generates a simple hash from an int64. */
- int generateHash (const int64 key, const int upperLimit) const noexcept { return std::abs ((int) key) % upperLimit; }
- /** Generates a simple hash from a string. */
- int generateHash (const String& key, const int upperLimit) const noexcept { return (int) (((uint32) key.hashCode()) % (uint32) upperLimit); }
- /** Generates a simple hash from a variant. */
- int generateHash (const var& key, const int upperLimit) const noexcept { return generateHash (key.toString(), upperLimit); }
-};
-
-#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
-
-//==============================================================================
-/**
- Holds a set of mappings between some key/value pairs.
-
- The types of the key and value objects are set as template parameters.
- You can also specify a class to supply a hash function that converts a key value
- into an hashed integer. This class must have the form:
-
- @code
- struct MyHashGenerator
- {
- int generateHash (MyKeyType key, int upperLimit)
- {
- // The function must return a value 0 <= x < upperLimit
- return someFunctionOfMyKeyType (key) % upperLimit;
- }
- };
- @endcode
-
- Like the Array class, the key and value types are expected to be copy-by-value
- types, so if you define them to be pointer types, this class won't delete the
- objects that they point to.
-
- If you don't supply a class for the HashFunctionToUse template parameter, the
- default one provides some simple mappings for strings and ints.
-
- @code
- HashMap hash;
- hash.set (1, "item1");
- hash.set (2, "item2");
-
- DBG (hash [1]); // prints "item1"
- DBG (hash [2]); // prints "item2"
-
- // This iterates the map, printing all of its key -> value pairs..
- for (HashMap::Iterator i (hash); i.next();)
- DBG (i.getKey() << " -> " << i.getValue());
- @endcode
-
- @tparam HashFunctionToUse The type of hash functions, which must be copy
- constructible.
-
- @see CriticalSection, DefaultHashFunctions, NamedValueSet, SortedSet
-*/
-template
-class HashMap
- : public Uncopyable
- , LeakChecked >
-{
-private:
- typedef PARAMETER_TYPE (KeyType) KeyTypeParameter;
- typedef PARAMETER_TYPE (ValueType) ValueTypeParameter;
-
-public:
- //==============================================================================
- /** Creates an empty hash-map.
-
- The numberOfSlots parameter specifies the number of hash entries the map will
- use. This will be the "upperLimit" parameter that is passed to your generateHash()
- function. The number of hash slots will grow automatically if necessary, or
- it can be remapped manually using remapTable().
-
- @param hashFunctionToUse An instance of HashFunctionToUse, which will be
- copied and stored to use with the HashMap. This
- can be left out if HashFunctionToUse has a default
- constructor.
- */
- explicit HashMap (const int numberOfSlots = defaultHashTableSize,
- HashFunctionToUse hashFunctionToUse_ = HashFunctionToUse ())
- : hashFunctionToUse (hashFunctionToUse_)
- , totalNumItems (0)
- {
- slots.insertMultiple (0, nullptr, numberOfSlots);
- }
-
- /** Destructor. */
- ~HashMap()
- {
- clear();
- }
-
- //==============================================================================
- /** Removes all values from the map.
- Note that this will clear the content, but won't affect the number of slots (see
- remapTable and getNumSlots).
- */
- void clear()
- {
- const ScopedLockType sl (getLock());
-
- for (int i = slots.size(); --i >= 0;)
- {
- HashEntry* h = slots.getUnchecked(i);
-
- while (h != nullptr)
- {
- const ScopedPointer deleter (h);
- h = h->nextEntry;
- }
-
- slots.set (i, nullptr);
- }
-
- totalNumItems = 0;
- }
-
- //==============================================================================
- /** Returns the current number of items in the map. */
- inline int size() const noexcept
- {
- return totalNumItems;
- }
-
- /** Returns the value corresponding to a given key.
- If the map doesn't contain the key, a default instance of the value type is returned.
- @param keyToLookFor the key of the item being requested
- */
- inline ValueType operator[] (KeyTypeParameter keyToLookFor) const
- {
- const ScopedLockType sl (getLock());
-
- for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
- if (entry->key == keyToLookFor)
- return entry->value;
-
- return ValueType();
- }
-
- //==============================================================================
- /** Returns true if the map contains an item with the specied key. */
- bool contains (KeyTypeParameter keyToLookFor) const
- {
- const ScopedLockType sl (getLock());
-
- for (const HashEntry* entry = slots.getUnchecked (generateHashFor (keyToLookFor)); entry != nullptr; entry = entry->nextEntry)
- if (entry->key == keyToLookFor)
- return true;
-
- return false;
- }
-
- /** Returns true if the hash contains at least one occurrence of a given value. */
- bool containsValue (ValueTypeParameter valueToLookFor) const
- {
- const ScopedLockType sl (getLock());
-
- for (int i = getNumSlots(); --i >= 0;)
- for (const HashEntry* entry = slots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
- if (entry->value == valueToLookFor)
- return true;
-
- return false;
- }
-
- //==============================================================================
- /** Adds or replaces an element in the hash-map.
- If there's already an item with the given key, this will replace its value. Otherwise, a new item
- will be added to the map.
- */
- void set (KeyTypeParameter newKey, ValueTypeParameter newValue)
- {
- const ScopedLockType sl (getLock());
- const int hashIndex = generateHashFor (newKey);
-
- HashEntry* const firstEntry = slots.getUnchecked (hashIndex);
-
- for (HashEntry* entry = firstEntry; entry != nullptr; entry = entry->nextEntry)
- {
- if (entry->key == newKey)
- {
- entry->value = newValue;
- return;
- }
- }
-
- slots.set (hashIndex, new HashEntry (newKey, newValue, firstEntry));
- ++totalNumItems;
-
- if (totalNumItems > (getNumSlots() * 3) / 2)
- remapTable (getNumSlots() * 2);
- }
-
- /** Removes an item with the given key. */
- void remove (KeyTypeParameter keyToRemove)
- {
- const ScopedLockType sl (getLock());
- const int hashIndex = generateHashFor (keyToRemove);
- HashEntry* entry = slots.getUnchecked (hashIndex);
- HashEntry* previous = nullptr;
-
- while (entry != nullptr)
- {
- if (entry->key == keyToRemove)
- {
- const ScopedPointer deleter (entry);
-
- entry = entry->nextEntry;
-
- if (previous != nullptr)
- previous->nextEntry = entry;
- else
- slots.set (hashIndex, entry);
-
- --totalNumItems;
- }
- else
- {
- previous = entry;
- entry = entry->nextEntry;
- }
- }
- }
-
- /** Removes all items with the given value. */
- void removeValue (ValueTypeParameter valueToRemove)
- {
- const ScopedLockType sl (getLock());
-
- for (int i = getNumSlots(); --i >= 0;)
- {
- HashEntry* entry = slots.getUnchecked(i);
- HashEntry* previous = nullptr;
-
- while (entry != nullptr)
- {
- if (entry->value == valueToRemove)
- {
- const ScopedPointer deleter (entry);
-
- entry = entry->nextEntry;
-
- if (previous != nullptr)
- previous->nextEntry = entry;
- else
- slots.set (i, entry);
-
- --totalNumItems;
- }
- else
- {
- previous = entry;
- entry = entry->nextEntry;
- }
- }
- }
- }
-
- /** Remaps the hash-map to use a different number of slots for its hash function.
- Each slot corresponds to a single hash-code, and each one can contain multiple items.
- @see getNumSlots()
- */
- void remapTable (int newNumberOfSlots)
- {
- HashMap newTable (newNumberOfSlots);
-
- for (int i = getNumSlots(); --i >= 0;)
- for (const HashEntry* entry = slots.getUnchecked(i); entry != nullptr; entry = entry->nextEntry)
- newTable.set (entry->key, entry->value);
-
- swapWith (newTable);
- }
-
- /** Returns the number of slots which are available for hashing.
- Each slot corresponds to a single hash-code, and each one can contain multiple items.
- @see getNumSlots()
- */
- inline int getNumSlots() const noexcept
- {
- return slots.size();
- }
-
- //==============================================================================
- /** Efficiently swaps the contents of two hash-maps. */
- template
- void swapWith (OtherHashMapType& otherHashMap) noexcept
- {
- const ScopedLockType lock1 (getLock());
- const typename OtherHashMapType::ScopedLockType lock2 (otherHashMap.getLock());
-
- slots.swapWith (otherHashMap.slots);
- std::swap (totalNumItems, otherHashMap.totalNumItems);
- }
-
- //==============================================================================
- /** Returns the CriticalSection that locks this structure.
- To lock, you can call getLock().enter() and getLock().exit(), or preferably use
- an object of ScopedLockType as an RAII lock for it.
- */
- inline const TypeOfCriticalSectionToUse& getLock() const noexcept { return lock; }
-
- /** Returns the type of scoped lock to use for locking this array */
- typedef typename TypeOfCriticalSectionToUse::ScopedLockType ScopedLockType;
-
-private:
- //==============================================================================
- class HashEntry : public Uncopyable
- {
- public:
- HashEntry (KeyTypeParameter k, ValueTypeParameter val, HashEntry* const next)
- : key (k), value (val), nextEntry (next)
- {}
-
- const KeyType key;
- ValueType value;
- HashEntry* nextEntry;
- };
-
-public:
- //==============================================================================
- /** Iterates over the items in a HashMap.
-
- To use it, repeatedly call next() until it returns false, e.g.
- @code
- HashMap myMap;
-
- HashMap::Iterator i (myMap);
-
- while (i.next())
- {
- DBG (i.getKey() << " -> " << i.getValue());
- }
- @endcode
-
- The order in which items are iterated bears no resemblence to the order in which
- they were originally added!
-
- Obviously as soon as you call any non-const methods on the original hash-map, any
- iterators that were created beforehand will cease to be valid, and should not be used.
-
- @see HashMap
- */
- class Iterator : LeakChecked , public Uncopyable
- {
- public:
- //==============================================================================
- Iterator (const HashMap& hashMapToIterate)
- : hashMap (hashMapToIterate), entry (nullptr), index (0)
- {}
-
- /** Moves to the next item, if one is available.
- When this returns true, you can get the item's key and value using getKey() and
- getValue(). If it returns false, the iteration has finished and you should stop.
- */
- bool next()
- {
- if (entry != nullptr)
- entry = entry->nextEntry;
-
- while (entry == nullptr)
- {
- if (index >= hashMap.getNumSlots())
- return false;
-
- entry = hashMap.slots.getUnchecked (index++);
- }
-
- return true;
- }
-
- /** Returns the current item's key.
- This should only be called when a call to next() has just returned true.
- */
- KeyType getKey() const
- {
- return entry != nullptr ? entry->key : KeyType();
- }
-
- /** Returns the current item's value.
- This should only be called when a call to next() has just returned true.
- */
- ValueType getValue() const
- {
- return entry != nullptr ? entry->value : ValueType();
- }
-
- private:
- //==============================================================================
- const HashMap& hashMap;
- HashEntry* entry;
- int index;
- };
-
-private:
- //==============================================================================
- enum { defaultHashTableSize = 101 };
- friend class Iterator;
-
- HashFunctionToUse const hashFunctionToUse;
- Array slots;
- int totalNumItems;
- TypeOfCriticalSectionToUse lock;
-
- int generateHashFor (KeyTypeParameter key) const
- {
- const int hash = hashFunctionToUse.generateHash (key, getNumSlots());
- bassert (isPositiveAndBelow (hash, getNumSlots())); // your hash function is generating out-of-range numbers!
- return hash;
- }
-};
-
-
-#endif // BEAST_HASHMAP_H_INCLUDED
diff --git a/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h b/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h
new file mode 100644
index 000000000..6b8fc502d
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/detail/copyconst.h
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#ifndef BEAST_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED
+#define BEAST_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED
+
+namespace detail
+{
+
+// Copy const attribute from T to U if present
+template
+struct copyconst
+{
+ typedef typename removecv ::type type;
+};
+
+template
+struct copyconst
+{
+ typedef U const type;
+};
+
+template
+struct copyconst
+{
+ typedef U type;
+};
+
+}
+
+#endif
diff --git a/Subtrees/beast/modules/beast_core/containers/detail/removecv.h b/Subtrees/beast/modules/beast_core/containers/detail/removecv.h
new file mode 100644
index 000000000..19b3d3bc4
--- /dev/null
+++ b/Subtrees/beast/modules/beast_core/containers/detail/removecv.h
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#ifndef BEAST_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED
+#define BEAST_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED
+
+namespace detail
+{
+
+// Strip all cv qualifiers from T
+template
+struct removecv
+{
+ typedef T type;
+};
+
+template
+struct removecv
+{
+ typedef typename removecv ::type type;
+};
+
+template
+struct removecv
+{
+ typedef typename removecv ::type type;
+};
+
+template
+struct removecv
+{
+ typedef typename removecv ::type type;
+};
+
+template
+struct removecv
+{
+ typedef typename removecv ::type type;
+};
+
+template