mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Rearrange sources (#4997)
This commit is contained in:
committed by
John Freeman
parent
2e902dee53
commit
e416ee72ca
51
include/xrpl/beast/core/CurrentThreadName.h
Normal file
51
include/xrpl/beast/core/CurrentThreadName.h
Normal file
@@ -0,0 +1,51 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
||||
#define BEAST_CORE_CURRENT_THREAD_NAME_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Changes the name of the caller thread.
|
||||
Different OSes may place different length or content limits on this name.
|
||||
*/
|
||||
void
|
||||
setCurrentThreadName(std::string_view newThreadName);
|
||||
|
||||
/** Returns the name of the caller thread.
|
||||
|
||||
The name returned is the name as set by a call to setCurrentThreadName().
|
||||
If the thread name is set by an external force, then that name change
|
||||
will not be reported.
|
||||
|
||||
If no name has ever been set, then the empty string is returned.
|
||||
*/
|
||||
std::string
|
||||
getCurrentThreadName();
|
||||
|
||||
} // namespace beast
|
||||
|
||||
#endif
|
||||
237
include/xrpl/beast/core/LexicalCast.h
Normal file
237
include/xrpl/beast/core/LexicalCast.h
Normal file
@@ -0,0 +1,237 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
|
||||
#define BEAST_MODULE_CORE_TEXT_LEXICALCAST_H_INCLUDED
|
||||
|
||||
#include <boost/core/detail/string_view.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <charconv>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// These specializatons get called by the non-member functions to do the work
|
||||
template <class Out, class In>
|
||||
struct LexicalCast;
|
||||
|
||||
// conversion to std::string
|
||||
template <class In>
|
||||
struct LexicalCast<std::string, In>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
template <class Arithmetic = In>
|
||||
std::enable_if_t<std::is_arithmetic_v<Arithmetic>, bool>
|
||||
operator()(std::string& out, Arithmetic in)
|
||||
{
|
||||
out = std::to_string(in);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Enumeration = In>
|
||||
std::enable_if_t<std::is_enum_v<Enumeration>, bool>
|
||||
operator()(std::string& out, Enumeration in)
|
||||
{
|
||||
out = std::to_string(
|
||||
static_cast<std::underlying_type_t<Enumeration>>(in));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Parse a std::string_view into a number
|
||||
template <typename Out>
|
||||
struct LexicalCast<Out, std::string_view>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
static_assert(
|
||||
std::is_integral_v<Out>,
|
||||
"beast::LexicalCast can only be used with integral types");
|
||||
|
||||
template <class Integral = Out>
|
||||
std::enable_if_t<
|
||||
std::is_integral_v<Integral> && !std::is_same_v<Integral, bool>,
|
||||
bool>
|
||||
operator()(Integral& out, std::string_view in) const
|
||||
{
|
||||
auto first = in.data();
|
||||
auto last = in.data() + in.size();
|
||||
|
||||
if (first != last && *first == '+')
|
||||
++first;
|
||||
|
||||
auto ret = std::from_chars(first, last, out);
|
||||
|
||||
return ret.ec == std::errc() && ret.ptr == last;
|
||||
}
|
||||
|
||||
bool
|
||||
operator()(bool& out, std::string_view in) const
|
||||
{
|
||||
std::string result;
|
||||
|
||||
// Convert the input to lowercase
|
||||
std::transform(
|
||||
in.begin(), in.end(), std::back_inserter(result), [](auto c) {
|
||||
return std::tolower(static_cast<unsigned char>(c));
|
||||
});
|
||||
|
||||
if (result == "1" || result == "true")
|
||||
{
|
||||
out = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result == "0" || result == "false")
|
||||
{
|
||||
out = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Parse boost library's string_view to number or boolean value
|
||||
// Note: As of Jan 2024, Boost contains three different types of string_view
|
||||
// (boost::core::basic_string_view<char>, boost::string_ref and
|
||||
// boost::string_view). The below template specialization is included because
|
||||
// it is used in the handshake.cpp file
|
||||
template <class Out>
|
||||
struct LexicalCast<Out, boost::core::basic_string_view<char>>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
bool
|
||||
operator()(Out& out, boost::core::basic_string_view<char> in) const
|
||||
{
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse std::string to number or boolean value
|
||||
template <class Out>
|
||||
struct LexicalCast<Out, std::string>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
bool
|
||||
operator()(Out& out, std::string in) const
|
||||
{
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
}
|
||||
};
|
||||
|
||||
// Conversion from null terminated char const*
|
||||
template <class Out>
|
||||
struct LexicalCast<Out, char const*>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
bool
|
||||
operator()(Out& out, char const* in) const
|
||||
{
|
||||
assert(in);
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
}
|
||||
};
|
||||
|
||||
// Conversion from null terminated char*
|
||||
// The string is not modified.
|
||||
template <class Out>
|
||||
struct LexicalCast<Out, char*>
|
||||
{
|
||||
explicit LexicalCast() = default;
|
||||
|
||||
bool
|
||||
operator()(Out& out, char* in) const
|
||||
{
|
||||
assert(in);
|
||||
return LexicalCast<Out, std::string_view>()(out, in);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Thrown when a conversion is not possible with LexicalCast.
|
||||
Only used in the throw variants of lexicalCast.
|
||||
*/
|
||||
struct BadLexicalCast : public std::bad_cast
|
||||
{
|
||||
explicit BadLexicalCast() = default;
|
||||
};
|
||||
|
||||
/** Intelligently convert from one type to another.
|
||||
@return `false` if there was a parsing or range error
|
||||
*/
|
||||
template <class Out, class In>
|
||||
bool
|
||||
lexicalCastChecked(Out& out, In in)
|
||||
{
|
||||
return detail::LexicalCast<Out, In>()(out, in);
|
||||
}
|
||||
|
||||
/** Convert from one type to another, throw on error
|
||||
|
||||
An exception of type BadLexicalCast is thrown if the conversion fails.
|
||||
|
||||
@return The new type.
|
||||
*/
|
||||
template <class Out, class In>
|
||||
Out
|
||||
lexicalCastThrow(In in)
|
||||
{
|
||||
if (Out out; lexicalCastChecked(out, in))
|
||||
return out;
|
||||
|
||||
throw BadLexicalCast();
|
||||
}
|
||||
|
||||
/** Convert from one type to another.
|
||||
|
||||
@param defaultValue The value returned if parsing fails
|
||||
@return The new type.
|
||||
*/
|
||||
template <class Out, class In>
|
||||
Out
|
||||
lexicalCast(In in, Out defaultValue = Out())
|
||||
{
|
||||
if (Out out; lexicalCastChecked(out, in))
|
||||
return out;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
|
||||
#endif
|
||||
599
include/xrpl/beast/core/List.h
Normal file
599
include/xrpl/beast/core/List.h
Normal file
@@ -0,0 +1,599 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_INTRUSIVE_LIST_H_INCLUDED
|
||||
#define BEAST_INTRUSIVE_LIST_H_INCLUDED
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template <typename, typename>
|
||||
class List;
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Copy `const` attribute from T to U if present. */
|
||||
/** @{ */
|
||||
template <typename T, typename U>
|
||||
struct CopyConst
|
||||
{
|
||||
explicit CopyConst() = default;
|
||||
|
||||
using type = typename std::remove_const<U>::type;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct CopyConst<T const, U>
|
||||
{
|
||||
explicit CopyConst() = default;
|
||||
|
||||
using type = typename std::remove_const<U>::type const;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
// This is the intrusive portion of the doubly linked list.
|
||||
// One derivation per list that the object may appear on
|
||||
// concurrently is required.
|
||||
//
|
||||
template <typename T, typename Tag>
|
||||
class ListNode
|
||||
{
|
||||
private:
|
||||
using value_type = T;
|
||||
|
||||
friend class List<T, Tag>;
|
||||
|
||||
template <typename>
|
||||
friend class ListIterator;
|
||||
|
||||
ListNode* m_next;
|
||||
ListNode* m_prev;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename N>
|
||||
class ListIterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type =
|
||||
typename beast::detail::CopyConst<N, typename N::value_type>::type;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using size_type = std::size_t;
|
||||
|
||||
ListIterator(N* node = nullptr) noexcept : m_node(node)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
ListIterator(ListIterator<M> const& other) noexcept : m_node(other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool
|
||||
operator==(ListIterator<M> const& other) const noexcept
|
||||
{
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool
|
||||
operator!=(ListIterator<M> 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<reference>(*m_node);
|
||||
}
|
||||
|
||||
void
|
||||
increment() noexcept
|
||||
{
|
||||
m_node = m_node->m_next;
|
||||
}
|
||||
|
||||
void
|
||||
decrement() noexcept
|
||||
{
|
||||
m_node = m_node->m_prev;
|
||||
}
|
||||
|
||||
N* m_node;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/** Intrusive doubly linked list.
|
||||
|
||||
This intrusive List is a container similar in operation to std::list in the
|
||||
Standard Template Library (STL). Like all @ref intrusive containers, List
|
||||
requires you to first derive your class from List<>::Node:
|
||||
|
||||
@code
|
||||
|
||||
struct Object : List <Object>::Node
|
||||
{
|
||||
explicit Object (int value) : m_value (value)
|
||||
{
|
||||
}
|
||||
|
||||
int m_value;
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
Now we define the list, and add a couple of items.
|
||||
|
||||
@code
|
||||
|
||||
List <Object> list;
|
||||
|
||||
list.push_back (* (new Object (1)));
|
||||
list.push_back (* (new Object (2)));
|
||||
|
||||
@endcode
|
||||
|
||||
For compatibility with the standard containers, push_back() expects a
|
||||
reference to the object. Unlike the standard container, however, push_back()
|
||||
places the actual object in the list and not a copy-constructed duplicate.
|
||||
|
||||
Iterating over the list follows the same idiom as the STL:
|
||||
|
||||
@code
|
||||
|
||||
for (List <Object>::iterator iter = list.begin(); iter != list.end; ++iter)
|
||||
std::cout << iter->m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
You can even use BOOST_FOREACH, or range based for loops:
|
||||
|
||||
@code
|
||||
|
||||
BOOST_FOREACH (Object& object, list) // boost only
|
||||
std::cout << object.m_value;
|
||||
|
||||
for (Object& object : list) // C++11 only
|
||||
std::cout << object.m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
Because List is mostly STL compliant, it can be passed into STL algorithms:
|
||||
e.g. `std::for_each()` or `std::find_first_of()`.
|
||||
|
||||
In general, objects placed into a List should be dynamically allocated
|
||||
although this cannot be enforced at compile time. Since the caller provides
|
||||
the storage for the object, the caller is also responsible for deleting the
|
||||
object. An object still exists after being removed from a List, until the
|
||||
caller deletes it. This means an element can be moved from one List to
|
||||
another with practically no overhead.
|
||||
|
||||
Unlike the standard containers, an object may only exist in one list at a
|
||||
time, unless special preparations are made. The Tag template parameter is
|
||||
used to distinguish between different list types for the same object,
|
||||
allowing the object to exist in more than one list simultaneously.
|
||||
|
||||
For example, consider an actor system where a global list of actors is
|
||||
maintained, so that they can each be periodically receive processing
|
||||
time. We wish to also maintain a list of the subset of actors that require
|
||||
a domain-dependent update. To achieve this, we declare two tags, the
|
||||
associated list types, and the list element thusly:
|
||||
|
||||
@code
|
||||
|
||||
struct Actor; // Forward declaration required
|
||||
|
||||
struct ProcessTag { };
|
||||
struct UpdateTag { };
|
||||
|
||||
using ProcessList = List <Actor, ProcessTag>;
|
||||
using UpdateList = List <Actor, UpdateTag>;
|
||||
|
||||
// Derive from both node types so we can be in each list at once.
|
||||
//
|
||||
struct Actor : ProcessList::Node, UpdateList::Node
|
||||
{
|
||||
bool process (); // returns true if we need an update
|
||||
void update ();
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
@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, when the object can exist in multiple lists simultaneously.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <typename T, typename Tag = void>
|
||||
class List
|
||||
{
|
||||
public:
|
||||
using Node = typename detail::ListNode<T, Tag>;
|
||||
|
||||
using value_type = T;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
using const_pointer = value_type const*;
|
||||
using const_reference = value_type const&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using iterator = detail::ListIterator<Node>;
|
||||
using const_iterator = detail::ListIterator<Node const>;
|
||||
|
||||
/** Create an empty list. */
|
||||
List()
|
||||
{
|
||||
m_head.m_prev = nullptr; // identifies the head
|
||||
m_tail.m_next = nullptr; // identifies the tail
|
||||
clear();
|
||||
}
|
||||
|
||||
List(List const&) = delete;
|
||||
List&
|
||||
operator=(List const&) = delete;
|
||||
|
||||
/** Determine if the list is empty.
|
||||
@return `true` if the list is empty.
|
||||
*/
|
||||
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() noexcept
|
||||
{
|
||||
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 noexcept
|
||||
{
|
||||
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() noexcept
|
||||
{
|
||||
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 noexcept
|
||||
{
|
||||
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() 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 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 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() 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 noexcept
|
||||
{
|
||||
return const_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
|
||||
cend() const noexcept
|
||||
{
|
||||
return const_iterator(&m_tail);
|
||||
}
|
||||
|
||||
/** Clear the list.
|
||||
@note This does not free the elements.
|
||||
*/
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
m_head.m_next = &m_tail;
|
||||
m_tail.m_prev = &m_head;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
/** Insert an element.
|
||||
@invariant The element must not already be in the list.
|
||||
@param pos The location to insert after.
|
||||
@param element The element to insert.
|
||||
@return An iterator pointing to the newly inserted element.
|
||||
*/
|
||||
iterator
|
||||
insert(iterator pos, T& element) noexcept
|
||||
{
|
||||
Node* node = static_cast<Node*>(&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;
|
||||
++m_size;
|
||||
return iterator(node);
|
||||
}
|
||||
|
||||
/** 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) noexcept
|
||||
{
|
||||
if (!other.empty())
|
||||
{
|
||||
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;
|
||||
before->m_prev = other.m_tail.m_prev;
|
||||
m_size += other.m_size;
|
||||
other.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** 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) noexcept
|
||||
{
|
||||
Node* node = &*pos;
|
||||
++pos;
|
||||
node->m_next->m_prev = node->m_prev;
|
||||
node->m_prev->m_next = node->m_next;
|
||||
--m_size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/** Insert an element at the beginning of the list.
|
||||
@invariant The element must not exist in the list.
|
||||
@param element The element to insert.
|
||||
*/
|
||||
iterator
|
||||
push_front(T& element) noexcept
|
||||
{
|
||||
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.
|
||||
*/
|
||||
T&
|
||||
pop_front() noexcept
|
||||
{
|
||||
T& element(front());
|
||||
erase(begin());
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Append an element at the end of the list.
|
||||
@invariant The element must not exist in the list.
|
||||
@param element The element to append.
|
||||
*/
|
||||
iterator
|
||||
push_back(T& element) noexcept
|
||||
{
|
||||
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.
|
||||
*/
|
||||
T&
|
||||
pop_back() noexcept
|
||||
{
|
||||
T& element(back());
|
||||
erase(--end());
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Swap contents with another list. */
|
||||
void
|
||||
swap(List& other) noexcept
|
||||
{
|
||||
List temp;
|
||||
temp.append(other);
|
||||
other.append(*this);
|
||||
append(temp);
|
||||
}
|
||||
|
||||
/** Insert another list at the beginning of this list.
|
||||
The other list is cleared.
|
||||
@param list The other list to insert.
|
||||
*/
|
||||
iterator
|
||||
prepend(List& list) noexcept
|
||||
{
|
||||
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.
|
||||
*/
|
||||
iterator
|
||||
append(List& list) noexcept
|
||||
{
|
||||
return insert(end(), list);
|
||||
}
|
||||
|
||||
/** Obtain an iterator from an element.
|
||||
@invariant The element must exist in the list.
|
||||
@param element The element to obtain an iterator for.
|
||||
@return An iterator to the element.
|
||||
*/
|
||||
iterator
|
||||
iterator_to(T& element) const noexcept
|
||||
{
|
||||
return iterator(static_cast<Node*>(&element));
|
||||
}
|
||||
|
||||
/** Obtain a const iterator from an element.
|
||||
@invariant The element must exist in the list.
|
||||
@param element The element to obtain an iterator for.
|
||||
@return A const iterator to the element.
|
||||
*/
|
||||
const_iterator
|
||||
const_iterator_to(T const& element) const noexcept
|
||||
{
|
||||
return const_iterator(static_cast<Node const*>(&element));
|
||||
}
|
||||
|
||||
private:
|
||||
reference
|
||||
element_from(Node* node) noexcept
|
||||
{
|
||||
return *(static_cast<pointer>(node));
|
||||
}
|
||||
|
||||
const_reference
|
||||
element_from(Node const* node) const noexcept
|
||||
{
|
||||
return *(static_cast<const_pointer>(node));
|
||||
}
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
Node m_head;
|
||||
Node m_tail;
|
||||
};
|
||||
|
||||
} // namespace beast
|
||||
|
||||
#endif
|
||||
307
include/xrpl/beast/core/LockFreeStack.h
Normal file
307
include/xrpl/beast/core/LockFreeStack.h
Normal file
@@ -0,0 +1,307 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
|
||||
#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED
|
||||
|
||||
#include <atomic>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Container, bool IsConst>
|
||||
class LockFreeStackIterator
|
||||
{
|
||||
protected:
|
||||
using Node = typename Container::Node;
|
||||
using NodePtr =
|
||||
typename std::conditional<IsConst, Node const*, Node*>::type;
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename Container::value_type;
|
||||
using difference_type = typename Container::difference_type;
|
||||
using pointer = typename std::conditional<
|
||||
IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type;
|
||||
using reference = typename std::conditional<
|
||||
IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type;
|
||||
|
||||
LockFreeStackIterator() : m_node()
|
||||
{
|
||||
}
|
||||
|
||||
LockFreeStackIterator(NodePtr node) : m_node(node)
|
||||
{
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
explicit LockFreeStackIterator(
|
||||
LockFreeStackIterator<Container, OtherIsConst> const& other)
|
||||
: m_node(other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
LockFreeStackIterator&
|
||||
operator=(NodePtr node)
|
||||
{
|
||||
m_node = node;
|
||||
return static_cast<LockFreeStackIterator&>(*this);
|
||||
}
|
||||
|
||||
LockFreeStackIterator&
|
||||
operator++()
|
||||
{
|
||||
m_node = m_node->m_next.load();
|
||||
return static_cast<LockFreeStackIterator&>(*this);
|
||||
}
|
||||
|
||||
LockFreeStackIterator
|
||||
operator++(int)
|
||||
{
|
||||
LockFreeStackIterator result(*this);
|
||||
m_node = m_node->m_next;
|
||||
return result;
|
||||
}
|
||||
|
||||
NodePtr
|
||||
node() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const
|
||||
{
|
||||
return *this->operator->();
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return static_cast<pointer>(m_node);
|
||||
}
|
||||
|
||||
private:
|
||||
NodePtr m_node;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class Container, bool LhsIsConst, bool RhsIsConst>
|
||||
bool
|
||||
operator==(
|
||||
LockFreeStackIterator<Container, LhsIsConst> const& lhs,
|
||||
LockFreeStackIterator<Container, RhsIsConst> const& rhs)
|
||||
{
|
||||
return lhs.node() == rhs.node();
|
||||
}
|
||||
|
||||
template <class Container, bool LhsIsConst, bool RhsIsConst>
|
||||
bool
|
||||
operator!=(
|
||||
LockFreeStackIterator<Container, LhsIsConst> const& lhs,
|
||||
LockFreeStackIterator<Container, RhsIsConst> const& rhs)
|
||||
{
|
||||
return lhs.node() != rhs.node();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Multiple Producer, Multiple Consumer (MPMC) intrusive stack.
|
||||
|
||||
This stack is implemented using the same intrusive interface as List.
|
||||
All mutations are lock-free.
|
||||
|
||||
The caller is responsible for preventing the "ABA" problem:
|
||||
http://en.wikipedia.org/wiki/ABA_problem
|
||||
|
||||
@param Tag A type name used to distinguish lists and nodes, for
|
||||
putting objects in multiple lists. If this parameter is
|
||||
omitted, the default tag is used.
|
||||
*/
|
||||
template <class Element, class Tag = void>
|
||||
class LockFreeStack
|
||||
{
|
||||
public:
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
Node() : m_next(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Node(Node* next) : m_next(next)
|
||||
{
|
||||
}
|
||||
|
||||
Node(Node const&) = delete;
|
||||
Node&
|
||||
operator=(Node const&) = delete;
|
||||
|
||||
private:
|
||||
friend class LockFreeStack;
|
||||
|
||||
template <class Container, bool IsConst>
|
||||
friend class LockFreeStackIterator;
|
||||
|
||||
std::atomic<Node*> m_next;
|
||||
};
|
||||
|
||||
public:
|
||||
using value_type = Element;
|
||||
using pointer = Element*;
|
||||
using reference = Element&;
|
||||
using const_pointer = Element const*;
|
||||
using const_reference = Element const&;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator = LockFreeStackIterator<LockFreeStack<Element, Tag>, false>;
|
||||
using const_iterator =
|
||||
LockFreeStackIterator<LockFreeStack<Element, Tag>, true>;
|
||||
|
||||
LockFreeStack() : m_end(nullptr), m_head(&m_end)
|
||||
{
|
||||
}
|
||||
|
||||
LockFreeStack(LockFreeStack const&) = delete;
|
||||
LockFreeStack&
|
||||
operator=(LockFreeStack const&) = delete;
|
||||
|
||||
/** Returns true if the stack is empty. */
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return m_head.load() == &m_end;
|
||||
}
|
||||
|
||||
/** Push a node onto the stack.
|
||||
The caller is responsible for preventing the ABA problem.
|
||||
This operation is lock-free.
|
||||
Thread safety:
|
||||
Safe to call from any thread.
|
||||
|
||||
@param node The node to push.
|
||||
|
||||
@return `true` if the stack was previously empty. If multiple threads
|
||||
are attempting to push, only one will receive `true`.
|
||||
*/
|
||||
// VFALCO NOTE Fix this, shouldn't it be a reference like intrusive list?
|
||||
bool
|
||||
push_front(Node* node)
|
||||
{
|
||||
bool first;
|
||||
Node* old_head = m_head.load(std::memory_order_relaxed);
|
||||
do
|
||||
{
|
||||
first = (old_head == &m_end);
|
||||
node->m_next = old_head;
|
||||
} while (!m_head.compare_exchange_strong(
|
||||
old_head,
|
||||
node,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed));
|
||||
return first;
|
||||
}
|
||||
|
||||
/** Pop an element off the stack.
|
||||
The caller is responsible for preventing the ABA problem.
|
||||
This operation is lock-free.
|
||||
Thread safety:
|
||||
Safe to call from any thread.
|
||||
|
||||
@return The element that was popped, or `nullptr` if the stack
|
||||
was empty.
|
||||
*/
|
||||
Element*
|
||||
pop_front()
|
||||
{
|
||||
Node* node = m_head.load();
|
||||
Node* new_head;
|
||||
do
|
||||
{
|
||||
if (node == &m_end)
|
||||
return nullptr;
|
||||
new_head = node->m_next.load();
|
||||
} while (!m_head.compare_exchange_strong(
|
||||
node,
|
||||
new_head,
|
||||
std::memory_order_release,
|
||||
std::memory_order_relaxed));
|
||||
return static_cast<Element*>(node);
|
||||
}
|
||||
|
||||
/** Return a forward iterator to the beginning or end of the stack.
|
||||
Undefined behavior results if push_front or pop_front is called
|
||||
while an iteration is in progress.
|
||||
Thread safety:
|
||||
Caller is responsible for synchronization.
|
||||
*/
|
||||
/** @{ */
|
||||
iterator
|
||||
begin()
|
||||
{
|
||||
return iterator(m_head.load());
|
||||
}
|
||||
|
||||
iterator
|
||||
end()
|
||||
{
|
||||
return iterator(&m_end);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
return const_iterator(m_head.load());
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const
|
||||
{
|
||||
return const_iterator(&m_end);
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cbegin() const
|
||||
{
|
||||
return const_iterator(m_head.load());
|
||||
}
|
||||
|
||||
const_iterator
|
||||
cend() const
|
||||
{
|
||||
return const_iterator(&m_end);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
Node m_end;
|
||||
std::atomic<Node*> m_head;
|
||||
};
|
||||
|
||||
} // namespace beast
|
||||
|
||||
#endif
|
||||
118
include/xrpl/beast/core/SemanticVersion.h
Normal file
118
include/xrpl/beast/core/SemanticVersion.h
Normal file
@@ -0,0 +1,118 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_MODULE_CORE_DIAGNOSTIC_SEMANTICVERSION_H_INCLUDED
|
||||
#define BEAST_MODULE_CORE_DIAGNOSTIC_SEMANTICVERSION_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** A Semantic Version number.
|
||||
|
||||
Identifies the build of a particular version of software using
|
||||
the Semantic Versioning Specification described here:
|
||||
|
||||
http://semver.org/
|
||||
*/
|
||||
class SemanticVersion
|
||||
{
|
||||
public:
|
||||
using identifier_list = std::vector<std::string>;
|
||||
|
||||
int majorVersion;
|
||||
int minorVersion;
|
||||
int patchVersion;
|
||||
|
||||
identifier_list preReleaseIdentifiers;
|
||||
identifier_list metaData;
|
||||
|
||||
SemanticVersion();
|
||||
|
||||
SemanticVersion(std::string const& version);
|
||||
|
||||
/** Parse a semantic version string.
|
||||
The parsing is as strict as possible.
|
||||
@return `true` if the string was parsed.
|
||||
*/
|
||||
bool
|
||||
parse(std::string const& input);
|
||||
|
||||
/** Produce a string from semantic version components. */
|
||||
std::string
|
||||
print() const;
|
||||
|
||||
inline bool
|
||||
isRelease() const noexcept
|
||||
{
|
||||
return preReleaseIdentifiers.empty();
|
||||
}
|
||||
inline bool
|
||||
isPreRelease() const noexcept
|
||||
{
|
||||
return !isRelease();
|
||||
}
|
||||
};
|
||||
|
||||
/** Compare two SemanticVersions against each other.
|
||||
The comparison follows the rules as per the specification.
|
||||
*/
|
||||
int
|
||||
compare(SemanticVersion const& lhs, SemanticVersion const& rhs);
|
||||
|
||||
inline bool
|
||||
operator==(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) == 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) != 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>=(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) >= 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<=(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) <= 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) > 0;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<(SemanticVersion const& lhs, SemanticVersion const& rhs)
|
||||
{
|
||||
return compare(lhs, rhs) < 0;
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user