Reorganize source files

This commit is contained in:
Vinnie Falco
2016-04-19 20:29:16 -04:00
parent 2cb3834bbb
commit 4469ff4b9a
422 changed files with 4031 additions and 13217 deletions

View File

@@ -22,7 +22,7 @@
#include <ripple/overlay/Peer.h>
#include <ripple/shamap/SHAMap.h>
#include <beast/clock/abstract_clock.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/core/Stoppable.h>
#include <memory>

View File

@@ -49,7 +49,7 @@
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/types.h>
#include <ripple/beast/core/LexicalCast.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <boost/optional.hpp>
#include <cassert>
#include <utility>

View File

@@ -26,7 +26,7 @@
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/SecretKey.h>
#include <beast/hash/hash_append.h>
#include <ripple/beast/hash/hash_append.h>
#include <chrono>
#include <cstdint>
#include <string>

View File

@@ -72,7 +72,7 @@
#include <ripple/unity/git_id.h>
#include <ripple/websocket/MakeServer.h>
#include <ripple/crypto/csprng.h>
#include <beast/asio/io_latency_probe.h>
#include <ripple/beast/asio/io_latency_probe.h>
#include <ripple/beast/core/LexicalCast.h>
#include <boost/asio/signal_set.hpp>
#include <boost/optional.hpp>

View File

@@ -36,11 +36,11 @@
#include <ripple/rpc/RPCHandler.h>
#include <ripple/server/Role.h>
#include <ripple/protocol/BuildInfo.h>
#include <beast/clock/basic_seconds_clock.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/core/Time.h>
#include <beast/unit_test.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/utility/Debug.h>
#include <beast/streams/debug_ostream.h>
#include <beast/detail/stream/debug_ostream.hpp>
#include <google/protobuf/stubs/common.h>
#include <boost/program_options.hpp>
#include <cstdlib>
@@ -194,7 +194,7 @@ static int runUnitTests(
std::string const& argument)
{
using namespace beast::unit_test;
beast::debug_ostream stream;
beast::detail::debug_ostream stream;
reporter r (stream);
r.arg(argument);
bool const failed (r.run_each_if (

View File

@@ -20,7 +20,7 @@
#include <ripple/app/misc/impl/AccountTxPaging.h>
#include <ripple/protocol/types.h>
#include <ripple/test/jtx.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <cstdlib>
#include <memory>
#include <vector>

View File

@@ -28,7 +28,7 @@
#include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/digest.h>
#include <ripple/protocol/TxFlags.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple
{

View File

@@ -17,7 +17,7 @@
#include <BeastConfig.h>
#include <ripple/test/jtx.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace test {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/test/jtx.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace test {

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/basics/chrono.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace test {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/tx/impl/OfferStream.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/test/jtx.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <algorithm>
namespace ripple {

View File

@@ -32,7 +32,7 @@
#include <ripple/rpc/RipplePathFind.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/test/jtx.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <chrono>
#include <condition_variable>
#include <mutex>

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <ripple/app/tx/impl/Taker.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/core/LexicalCast.h>
#include <type_traits>

View File

@@ -21,8 +21,8 @@
#define RIPPLE_BASICS_BASICCONFIG_H_INCLUDED
#include <ripple/basics/contract.h>
#include <beast/unit_test/const_container.h>
#include <beast/ci_char_traits.h>
#include <beast/detail/const_container.hpp>
#include <beast/detail/ci_char_traits.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <map>
@@ -40,8 +40,8 @@ using IniFileSections = std::map<std::string, std::vector<std::string>>;
A configuration file contains zero or more sections.
*/
class Section
: public beast::const_container <
std::map <std::string, std::string, beast::ci_less>>
: public beast::detail::const_container <
std::map <std::string, std::string, beast::detail::ci_less>>
{
private:
std::string name_;
@@ -165,7 +165,7 @@ public:
class BasicConfig
{
private:
std::map <std::string, Section, beast::ci_less> map_;
std::map <std::string, Section, beast::detail::ci_less> map_;
public:
/** Returns `true` if a section with the given name exists. */

View File

@@ -22,7 +22,7 @@
#include <ripple/basics/hardened_hash.h>
#include <ripple/basics/UnorderedContainers.h>
#include <beast/clock/abstract_clock.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/beast/insight/Insight.h>
#include <mutex>

View File

@@ -21,7 +21,7 @@
#define RIPPLE_BASICS_LOG_H_INCLUDED
#include <ripple/basics/UnorderedContainers.h>
#include <beast/ci_char_traits.h>
#include <beast/detail/ci_char_traits.hpp>
#include <ripple/beast/utility/Journal.h>
#include <boost/filesystem.hpp>
#include <map>
@@ -148,7 +148,7 @@ private:
std::mutex mutable mutex_;
std::map <std::string,
std::unique_ptr<beast::Journal::Sink>,
beast::ci_less> sinks_;
beast::detail::ci_less> sinks_;
beast::severities::Severity thresh_;
File file_;
bool silent_ = false;

View File

@@ -23,7 +23,7 @@
#include <ripple/basics/hardened_hash.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/UnorderedContainers.h>
#include <beast/clock/abstract_clock.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/beast/insight/Insight.h>
#include <functional>
#include <mutex>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_BASICS_TESTSUITE_H_INCLUDED
#define RIPPLE_BASICS_TESTSUITE_H_INCLUDED
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <string>
namespace ripple {

View File

@@ -21,9 +21,9 @@
#define RIPPLE_BASICS_UNORDEREDCONTAINERS_H_INCLUDED
#include <ripple/basics/hardened_hash.h>
#include <beast/hash/hash_append.h>
#include <beast/hash/uhash.h>
#include <beast/hash/xxhasher.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/hash/uhash.h>
#include <ripple/beast/hash/xxhasher.h>
#include <unordered_map>
#include <unordered_set>

View File

@@ -20,9 +20,9 @@
#ifndef RIPPLE_BASICS_CHRONO_H_INCLUDED
#define RIPPLE_BASICS_CHRONO_H_INCLUDED
#include <beast/clock/abstract_clock.h>
#include <beast/clock/basic_seconds_clock.h>
#include <beast/clock/manual_clock.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/clock/manual_clock.h>
#include <chrono>
#include <cstdint>

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_BASICS_HARDENED_HASH_H_INCLUDED
#define RIPPLE_BASICS_HARDENED_HASH_H_INCLUDED
#include <beast/hash/hash_append.h>
#include <beast/hash/xxhasher.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/hash/xxhasher.h>
#include <cstdint>
#include <functional>

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/impl/CheckLibraryVersionsImpl.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/core/SemanticVersion.h>
#include <boost/version.hpp>
#include <openssl/opensslv.h>

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/RangeSet.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/core/LexicalCast.h>
#include <boost/foreach.hpp>
#include <cassert>

View File

@@ -21,7 +21,7 @@
#include <ripple/basics/ResolverAsio.h>
#include <ripple/basics/Log.h>
#include <ripple/beast/net/IPAddressConversion.h>
#include <beast/asio/placeholders.h>
#include <beast/placeholders.hpp>
#include <ripple/beast/core/WaitableEvent.h>
#include <boost/asio.hpp>
#include <atomic>

View File

@@ -22,7 +22,7 @@
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/ToString.h>
#include <ripple/beast/core/LexicalCast.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <boost/algorithm/string.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/regex.hpp>

View File

@@ -21,8 +21,8 @@
#define RIPPLE_BASICS_RANDOM_H_INCLUDED
#include <ripple/basics/win32_workaround.h>
#include <beast/xor_shift_engine.h>
#include <beast/is_call_possible.h>
#include <ripple/beast/xor_shift_engine.h>
#include <beast/detail/is_call_possible.hpp>
#include <boost/thread/tss.hpp>
#include <cassert>
#include <cstddef>
@@ -50,7 +50,7 @@ namespace detail {
// Determines if a type can be called like an Engine
template <class Engine, class Result = typename Engine::result_type>
using is_engine =
beast::is_call_possible<Engine, Result()>;
beast::detail::is_call_possible<Engine, Result()>;
}
/** Return the default random engine.

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/basics/CheckLibraryVersions.h>
#include <ripple/basics/impl/CheckLibraryVersionsImpl.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace version {

View File

@@ -20,8 +20,8 @@
#include <BeastConfig.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/KeyCache.h>
#include <beast/unit_test/suite.h>
#include <beast/clock/manual_clock.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/clock/manual_clock.h>
namespace ripple {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/RangeSet.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/ToString.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {

View File

@@ -20,8 +20,8 @@
#include <BeastConfig.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/TaggedCache.h>
#include <beast/unit_test/suite.h>
#include <beast/clock/manual_clock.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/clock/manual_clock.h>
namespace ripple {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <string>
namespace ripple {

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/hardened_hash.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <boost/functional/hash.hpp>
#include <array>
#include <cstdint>

View File

@@ -19,7 +19,7 @@
#include <BeastConfig.h>
#include <ripple/basics/mulDiv.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace test {

View File

@@ -0,0 +1,244 @@
//------------------------------------------------------------------------------
/*
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_ASIO_IO_LATENCY_PROBE_H_INCLUDED
#define BEAST_ASIO_IO_LATENCY_PROBE_H_INCLUDED
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/config.hpp>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <stdexcept>
namespace beast {
/** Measures handler latency on an io_service queue. */
template <class Clock>
class io_latency_probe
{
private:
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
std::recursive_mutex m_mutex;
std::condition_variable_any m_cond;
std::size_t m_count;
duration const m_period;
boost::asio::io_service& m_ios;
boost::asio::deadline_timer m_timer;
bool m_cancel;
public:
io_latency_probe (duration const& period,
boost::asio::io_service& ios)
: m_count (1)
, m_period (period)
, m_ios (ios)
, m_timer (m_ios)
, m_cancel (false)
{
}
~io_latency_probe ()
{
std::unique_lock <decltype (m_mutex)> lock (m_mutex);
cancel (lock, true);
}
/** Return the io_service associated with the latency probe. */
/** @{ */
boost::asio::io_service& get_io_service ()
{
return m_ios;
}
boost::asio::io_service const& get_io_service () const
{
return m_ios;
}
/** @} */
/** Cancel all pending i/o.
Any handlers which have already been queued will still be called.
*/
/** @{ */
void cancel ()
{
std::unique_lock <decltype(m_mutex)> lock (m_mutex);
cancel (lock, true);
}
void cancel_async ()
{
std::unique_lock <decltype(m_mutex)> lock (m_mutex);
cancel (lock, false);
}
/** @} */
/** Measure one sample of i/o latency.
Handler will be called with this signature:
void Handler (Duration d);
*/
template <class Handler>
void sample_one (Handler&& handler)
{
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
if (m_cancel)
throw std::logic_error ("io_latency_probe is canceled");
m_ios.post (sample_op <Handler> (
std::forward <Handler> (handler),
Clock::now(), false, this));
}
/** Initiate continuous i/o latency sampling.
Handler will be called with this signature:
void Handler (std::chrono::milliseconds);
*/
template <class Handler>
void sample (Handler&& handler)
{
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
if (m_cancel)
throw std::logic_error ("io_latency_probe is canceled");
m_ios.post (sample_op <Handler> (
std::forward <Handler> (handler),
Clock::now(), true, this));
}
private:
void cancel (std::unique_lock <decltype (m_mutex)>& lock,
bool wait)
{
if (! m_cancel)
{
--m_count;
m_cancel = true;
}
if (wait)
#ifdef BOOST_NO_CXX11_LAMBDAS
while (m_count != 0)
m_cond.wait (lock);
#else
m_cond.wait (lock, [this] {
return this->m_count == 0; });
#endif
}
void addref ()
{
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
++m_count;
}
void release ()
{
std::lock_guard <decltype(m_mutex)> lock (m_mutex);
if (--m_count == 0)
m_cond.notify_all ();
}
template <class Handler>
struct sample_op
{
Handler m_handler;
time_point m_start;
bool m_repeat;
io_latency_probe* m_probe;
sample_op (Handler const& handler, time_point const& start,
bool repeat, io_latency_probe* probe)
: m_handler (handler)
, m_start (start)
, m_repeat (repeat)
, m_probe (probe)
{
m_probe->addref();
}
sample_op (sample_op const& other)
: m_handler (other.m_handler)
, m_start (other.m_start)
, m_probe (other.m_probe)
{
m_probe->addref();
}
~sample_op ()
{
m_probe->release();
}
void operator() () const
{
typename Clock::time_point const now (Clock::now());
typename Clock::duration const elapsed (now - m_start);
m_handler (elapsed);
{
std::lock_guard <decltype (m_probe->m_mutex)
> lock (m_probe->m_mutex);
if (m_probe->m_cancel)
return;
}
if (m_repeat)
{
// Calculate when we want to sample again, and
// adjust for the expected latency.
//
typename Clock::time_point const when (
now + m_probe->m_period - 2 * elapsed);
if (when <= now)
{
// The latency is too high to maintain the desired
// period so don't bother with a timer.
//
m_probe->m_ios.post (sample_op <Handler> (
m_handler, now, m_repeat, m_probe));
}
else
{
boost::posix_time::microseconds mms (
std::chrono::duration_cast <
std::chrono::microseconds> (
when - now).count ());
m_probe->m_timer.expires_from_now (mms);
m_probe->m_timer.async_wait (sample_op <Handler> (
m_handler, now, m_repeat, m_probe));
}
}
}
void operator () (boost::system::error_code const& ec)
{
typename Clock::time_point const now (Clock::now());
m_probe->m_ios.post (sample_op <Handler> (
m_handler, now, m_repeat, m_probe));
}
};
};
}
#endif

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
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_ASIO_SSL_BUNDLE_H_INCLUDED
#define BEAST_ASIO_SSL_BUNDLE_H_INCLUDED
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <memory>
#include <utility>
namespace beast {
namespace asio {
/** Work-around for non-movable boost::ssl::stream.
This allows ssl::stream to be movable and allows the stream to
construct from an already-existing socket.
*/
struct ssl_bundle
{
using socket_type = boost::asio::ip::tcp::socket;
using stream_type = boost::asio::ssl::stream <socket_type&>;
using shared_context = std::shared_ptr<boost::asio::ssl::context>;
template <class... Args>
ssl_bundle (shared_context const& context_, Args&&... args);
// DEPRECATED
template <class... Args>
ssl_bundle (boost::asio::ssl::context& context_, Args&&... args);
shared_context context;
socket_type socket;
stream_type stream;
};
template <class... Args>
ssl_bundle::ssl_bundle (shared_context const& context_, Args&&... args)
: socket(std::forward<Args>(args)...)
, stream (socket, *context_)
{
}
template <class... Args>
ssl_bundle::ssl_bundle (boost::asio::ssl::context& context_, Args&&... args)
: socket(std::forward<Args>(args)...)
, stream (socket, context_)
{
}
} // asio
} // beast
#endif

View File

@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
/*
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_ASIO_SSL_ERROR_H_INCLUDED
#define BEAST_ASIO_SSL_ERROR_H_INCLUDED
#include <boost/asio.hpp>
//#include <boost/asio/error.hpp> // Causes error with WinSock.h
#include <boost/asio/ssl/error.hpp>
#include <boost/lexical_cast.hpp>
namespace beast {
/** Returns a human readable message if the error code is SSL related. */
template<class = void>
std::string
error_message_with_ssl(boost::system::error_code const& ec)
{
std::string error;
if (ec.category() == boost::asio::error::get_ssl_category())
{
error = " ("
+ boost::lexical_cast<std::string>(ERR_GET_LIB (ec.value ()))
+ ","
+ boost::lexical_cast<std::string>(ERR_GET_FUNC (ec.value ()))
+ ","
+ boost::lexical_cast<std::string>(ERR_GET_REASON (ec.value ()))
+ ") ";
// This buffer must be at least 120 bytes, most examples use 256.
// https://www.openssl.org/docs/crypto/ERR_error_string.html
char buf[256];
::ERR_error_string_n(ec.value (), buf, sizeof(buf));
error += buf;
}
else
{
error = ec.message();
}
return error;
}
/** Returns `true` if the error code is a SSL "short read." */
inline
bool
is_short_read(boost::system::error_code const& ec)
{
return (ec.category() == boost::asio::error::get_ssl_category())
&& (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ);
}
} // beast
#endif

View File

@@ -0,0 +1,111 @@
//------------------------------------------------------------------------------
/*
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_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
#define BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED
#include <chrono>
#include <string>
namespace beast {
/** Abstract interface to a clock.
This makes now() a member function instead of a static member, so
an instance of the class can be dependency injected, facilitating
unit tests where time may be controlled.
An abstract_clock inherits all the nested types of the Clock
template parameter.
Example:
@code
struct Implementation
{
using clock_type = abstract_clock <std::chrono::steady_clock>;
clock_type& clock_;
explicit Implementation (clock_type& clock)
: clock_(clock)
{
}
};
@endcode
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class Clock>
class abstract_clock
{
public:
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
using clock_type = Clock;
static bool const is_steady = Clock::is_steady;
virtual ~abstract_clock() = default;
/** Returns the current time. */
virtual time_point now() const = 0;
};
//------------------------------------------------------------------------------
namespace detail {
template <class Facade, class Clock>
struct abstract_clock_wrapper
: public abstract_clock<Facade>
{
using typename abstract_clock<Facade>::duration;
using typename abstract_clock<Facade>::time_point;
time_point
now() const override
{
return Clock::now();
}
};
}
//------------------------------------------------------------------------------
/** Returns a global instance of an abstract clock.
@tparam Facade A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
@tparam Clock The actual concrete clock to use.
*/
template<class Facade, class Clock = Facade>
abstract_clock<Facade>&
get_abstract_clock()
{
static detail::abstract_clock_wrapper<Facade, Clock> clock;
return clock;
}
}
#endif

View File

@@ -0,0 +1,217 @@
//------------------------------------------------------------------------------
/*
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_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED
#define BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED
#include <ripple/beast/clock/chrono_util.h>
#include <algorithm>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <vector>
namespace beast {
namespace detail {
class seconds_clock_worker
{
public:
virtual void sample () = 0;
};
//------------------------------------------------------------------------------
// Updates the clocks
class seconds_clock_thread
{
public:
using mutex = std::mutex;
using cond_var = std::condition_variable;
using lock_guard = std::lock_guard <mutex>;
using unique_lock = std::unique_lock <mutex>;
using clock_type = std::chrono::steady_clock;
using seconds = std::chrono::seconds;
using thread = std::thread;
using workers = std::vector <seconds_clock_worker*>;
bool stop_;
mutex mutex_;
cond_var cond_;
workers workers_;
thread thread_;
seconds_clock_thread ()
: stop_ (false)
{
thread_ = thread (std::bind(
&seconds_clock_thread::run, this));
}
~seconds_clock_thread ()
{
stop();
}
void add (seconds_clock_worker& w)
{
lock_guard lock (mutex_);
workers_.push_back (&w);
}
void remove (seconds_clock_worker& w)
{
lock_guard lock (mutex_);
workers_.erase (std::find (
workers_.begin (), workers_.end(), &w));
}
void stop()
{
if (thread_.joinable())
{
{
lock_guard lock (mutex_);
stop_ = true;
}
cond_.notify_all();
thread_.join();
}
}
void run()
{
unique_lock lock (mutex_);;
for (;;)
{
for (auto iter : workers_)
iter->sample();
using namespace std::chrono;
clock_type::time_point const when (
floor <seconds> (
clock_type::now().time_since_epoch()) +
seconds (1));
if (cond_.wait_until (lock, when, [this]{ return stop_; }))
return;
}
}
static seconds_clock_thread& instance ()
{
static seconds_clock_thread singleton;
return singleton;
}
};
}
//------------------------------------------------------------------------------
/** Called before main exits to terminate the utility thread.
This is a workaround for Visual Studio 2013:
http://connect.microsoft.com/VisualStudio/feedback/details/786016/creating-a-global-c-object-that-used-thread-join-in-its-destructor-causes-a-lockup
http://stackoverflow.com/questions/10915233/stdthreadjoin-hangs-if-called-after-main-exits-when-using-vs2012-rc
*/
inline
void
basic_seconds_clock_main_hook()
{
#ifdef _MSC_VER
detail::seconds_clock_thread::instance().stop();
#endif
}
/** A clock whose minimum resolution is one second.
The purpose of this class is to optimize the performance of the now()
member function call. It uses a dedicated thread that wakes up at least
once per second to sample the requested trivial clock.
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class Clock>
class basic_seconds_clock
{
public:
using rep = typename Clock::rep;
using period = typename Clock::period;
using duration = typename Clock::duration;
using time_point = typename Clock::time_point;
static bool const is_steady = Clock::is_steady;
static time_point now()
{
// Make sure the thread is constructed before the
// worker otherwise we will crash during destruction
// of objects with static storage duration.
struct initializer
{
initializer ()
{
detail::seconds_clock_thread::instance();
}
};
static initializer init;
struct worker : detail::seconds_clock_worker
{
time_point m_now;
std::mutex mutex_;
worker()
: m_now(Clock::now())
{
detail::seconds_clock_thread::instance().add(*this);
}
~worker()
{
detail::seconds_clock_thread::instance().remove(*this);
}
time_point now()
{
std::lock_guard<std::mutex> lock (mutex_);
return m_now;
}
void sample()
{
std::lock_guard<std::mutex> lock (mutex_);
m_now = Clock::now();
}
};
static worker w;
return w.now();
}
};
}
#endif

View File

@@ -0,0 +1,68 @@
//------------------------------------------------------------------------------
/*
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_CHRONO_CHRONO_UTIL_H_INCLUDED
#define BEAST_CHRONO_CHRONO_UTIL_H_INCLUDED
// From Howard Hinnant
// http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html
#if !defined(_MSC_FULL_VER) || (_MSC_FULL_VER <= 190023506)
// round down
template <class To, class Rep, class Period>
To floor(std::chrono::duration <Rep, Period> const& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t > d)
--t;
return t;
}
// round to nearest, to even on tie
template <class To, class Rep, class Period>
To round (std::chrono::duration <Rep, Period> const& d)
{
To t0 = std::chrono::duration_cast<To>(d);
To t1 = t0;
++t1;
auto diff0 = d - t0;
auto diff1 = t1 - d;
if (diff0 == diff1)
{
if (t0.count() & 1)
return t1;
return t0;
}
else if (diff0 < diff1)
return t0;
return t1;
}
// round up
template <class To, class Rep, class Period>
To ceil (std::chrono::duration <Rep, Period> const& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t < d)
++t;
return t;
}
#endif
#endif

View File

@@ -0,0 +1,100 @@
//------------------------------------------------------------------------------
/*
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_CHRONO_MANUAL_CLOCK_H_INCLUDED
#define BEAST_CHRONO_MANUAL_CLOCK_H_INCLUDED
#include <ripple/beast/clock/abstract_clock.h>
#include <cassert>
namespace beast {
/** Manual clock implementation.
This concrete class implements the @ref abstract_clock interface and
allows the time to be advanced manually, mainly for the purpose of
providing a clock in unit tests.
@tparam Clock A type meeting these requirements:
http://en.cppreference.com/w/cpp/concept/Clock
*/
template <class Clock>
class manual_clock
: public abstract_clock<Clock>
{
public:
using typename abstract_clock<Clock>::rep;
using typename abstract_clock<Clock>::duration;
using typename abstract_clock<Clock>::time_point;
private:
time_point now_;
public:
explicit
manual_clock (time_point const& now = time_point(duration(0)))
: now_(now)
{
}
time_point
now() const override
{
return now_;
}
/** Set the current time of the manual clock. */
void
set (time_point const& when)
{
assert(! Clock::is_steady || when >= now_);
now_ = when;
}
/** Convenience for setting the time in seconds from epoch. */
template <class Integer>
void
set(Integer seconds_from_epoch)
{
set(time_point(duration(
std::chrono::seconds(seconds_from_epoch))));
}
/** Advance the clock by a duration. */
template <class Rep, class Period>
void
advance(std::chrono::duration<Rep, Period> const& elapsed)
{
assert(! Clock::is_steady ||
(now_ + elapsed) >= now_);
now_ += elapsed;
}
/** Convenience for advancing the clock by one second. */
manual_clock&
operator++ ()
{
advance(std::chrono::seconds(1));
return *this;
}
};
}
#endif

View File

@@ -0,0 +1,93 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
// MODULES: ../impl/chrono_io.cpp
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/beast/clock/manual_clock.h>
#include <ripple/beast/unit_test.h>
#include <sstream>
#include <string>
#include <thread>
namespace beast {
class abstract_clock_test : public unit_test::suite
{
public:
template <class Clock>
void test (abstract_clock<Clock>& c)
{
{
auto const t1 (c.now ());
std::this_thread::sleep_for (
std::chrono::milliseconds (1500));
auto const t2 (c.now ());
std::stringstream ss;
ss <<
"t1= " << t1.time_since_epoch().count() <<
", t2= " << t2.time_since_epoch().count() <<
", elapsed= " << (t2 - t1).count();
log << ss.str();
}
}
void test_manual ()
{
using clock_type = manual_clock<std::chrono::steady_clock>;
clock_type c;
std::stringstream ss;
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
c.set (clock_type::time_point (std::chrono::seconds(1)));
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
c.set (clock_type::time_point (std::chrono::seconds(2)));
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
log << ss.str();
}
void run ()
{
log << "steady_clock";
test (get_abstract_clock<
std::chrono::steady_clock>());
log << "system_clock";
test (get_abstract_clock<
std::chrono::system_clock>());
log << "high_resolution_clock";
test (get_abstract_clock<
std::chrono::high_resolution_clock>());
log << "manual_clock";
test_manual ();
pass ();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(abstract_clock,chrono,beast);
}

View File

@@ -17,47 +17,24 @@
*/
//==============================================================================
#include <ripple/beast/net/URL.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
namespace beast {
class URL_test : public unit_test::suite
class basic_seconds_clock_test : public unit_test::suite
{
public:
void check_url_parsing (std::string const& url, bool expected)
{
auto result = parse_URL (url);
expect (result.first == expected,
(expected ? "Failed to parse " : "Succeeded in parsing ") + url);
expect (to_string (result.second) == url);
}
void test_url_parsing ()
{
char const* const urls[] =
{
"http://en.wikipedia.org/wiki/URI#Examples_of_URI_references",
"ftp://ftp.funet.fi/pub/standards/RFC/rfc959.txt"
"ftp://test:test@example.com:21/path/specifier/is/here"
"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
"foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose",
};
testcase ("URL parsing");
for (auto url : urls)
check_url_parsing (url, true);
}
void
run ()
run()
{
test_url_parsing ();
basic_seconds_clock <
std::chrono::steady_clock>::now ();
pass ();
}
};
BEAST_DEFINE_TESTSUITE(URL,http,beast);
BEAST_DEFINE_TESTSUITE(basic_seconds_clock,chrono,beast);
}

View File

@@ -23,8 +23,8 @@
#include <ripple/beast/container/detail/aged_container_iterator.h>
#include <ripple/beast/container/detail/aged_associative_container.h>
#include <ripple/beast/container/aged_container.h>
#include <beast/clock/abstract_clock.h>
#include <beast/empty_base_optimization.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <beast/detail/empty_base_optimization.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/version.hpp>
@@ -33,7 +33,7 @@
#include <initializer_list>
#include <iterator>
#include <memory>
#include <beast/cxx17/type_traits.h> // <type_traits>
#include <ripple/beast/cxx17/type_traits.h> // <type_traits>
#include <utility>
namespace beast {
@@ -445,13 +445,13 @@ public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = detail::aged_container_iterator<
using iterator = beast::detail::aged_container_iterator<
! IsMap, typename cont_type::iterator>;
using const_iterator = detail::aged_container_iterator<
using const_iterator = beast::detail::aged_container_iterator<
true, typename cont_type::iterator>;
using reverse_iterator = detail::aged_container_iterator<
using reverse_iterator = beast::detail::aged_container_iterator<
! IsMap, typename cont_type::reverse_iterator>;
using const_reverse_iterator = detail::aged_container_iterator<
using const_reverse_iterator = beast::detail::aged_container_iterator<
true, typename cont_type::reverse_iterator>;
//--------------------------------------------------------------------------
@@ -468,13 +468,13 @@ public:
public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = detail::aged_container_iterator<
using iterator = beast::detail::aged_container_iterator<
! IsMap, typename list_type::iterator>;
using const_iterator = detail::aged_container_iterator<
using const_iterator = beast::detail::aged_container_iterator<
true, typename list_type::iterator>;
using reverse_iterator = detail::aged_container_iterator<
using reverse_iterator = beast::detail::aged_container_iterator<
! IsMap, typename list_type::reverse_iterator>;
using const_reverse_iterator = detail::aged_container_iterator<
using const_reverse_iterator = beast::detail::aged_container_iterator<
true, typename list_type::reverse_iterator>;
iterator begin ()
@@ -966,16 +966,16 @@ public:
// enable_if prevents erase (reverse_iterator pos) from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos);
beast::detail::aged_container_iterator <false, Iterator, Base>
erase (beast::detail::aged_container_iterator <is_const, Iterator, Base> pos);
// enable_if prevents erase (reverse_iterator first, reverse_iterator last)
// from compiling
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
detail::aged_container_iterator <is_const, Iterator, Base> last);
beast::detail::aged_container_iterator <false, Iterator, Base>
erase (beast::detail::aged_container_iterator <is_const, Iterator, Base> first,
beast::detail::aged_container_iterator <is_const, Iterator, Base> last);
template <class K>
auto
@@ -991,7 +991,7 @@ public:
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void
touch (detail::aged_container_iterator <is_const, Iterator, Base> pos)
touch (beast::detail::aged_container_iterator <is_const, Iterator, Base> pos)
{
touch (pos, clock().now());
}
@@ -1220,7 +1220,7 @@ private:
template <bool is_const, class Iterator, class Base,
class = std::enable_if_t<!is_boost_reverse_iterator<Iterator>::value>>
void
touch (detail::aged_container_iterator <
touch (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now);
@@ -1768,27 +1768,27 @@ emplace_hint (const_iterator hint, Args&&... args) ->
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
beast::detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
erase (detail::aged_container_iterator <is_const, Iterator, Base> pos)
erase (beast::detail::aged_container_iterator <is_const, Iterator, Base> pos)
{
unlink_and_delete_element(&*((pos++).iterator()));
return detail::aged_container_iterator <
return beast::detail::aged_container_iterator <
false, Iterator, Base> (pos.iterator());
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Compare, class Allocator>
template <bool is_const, class Iterator, class Base, class>
detail::aged_container_iterator <false, Iterator, Base>
beast::detail::aged_container_iterator <false, Iterator, Base>
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
erase (detail::aged_container_iterator <is_const, Iterator, Base> first,
detail::aged_container_iterator <is_const, Iterator, Base> last)
erase (beast::detail::aged_container_iterator <is_const, Iterator, Base> first,
beast::detail::aged_container_iterator <is_const, Iterator, Base> last)
{
for (; first != last;)
unlink_and_delete_element(&*((first++).iterator()));
return detail::aged_container_iterator <
return beast::detail::aged_container_iterator <
false, Iterator, Base> (first.iterator());
}
@@ -1884,7 +1884,7 @@ template <bool IsMulti, bool IsMap, class Key, class T,
template <bool is_const, class Iterator, class Base, class>
void
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
touch (detail::aged_container_iterator <
touch (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now)
{
@@ -1923,7 +1923,7 @@ swap_data (aged_ordered_container& other) noexcept
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Compare, class Allocator>
struct is_aged_container <detail::aged_ordered_container <
struct is_aged_container <beast::detail::aged_ordered_container <
IsMulti, IsMap, Key, T, Clock, Compare, Allocator>>
: std::true_type
{
@@ -1934,9 +1934,9 @@ struct is_aged_container <detail::aged_ordered_container <
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Compare, class Allocator>
void swap (
detail::aged_ordered_container <IsMulti, IsMap,
beast::detail::aged_ordered_container <IsMulti, IsMap,
Key, T, Clock, Compare, Allocator>& lhs,
detail::aged_ordered_container <IsMulti, IsMap,
beast::detail::aged_ordered_container <IsMulti, IsMap,
Key, T, Clock, Compare, Allocator>& rhs) noexcept
{
lhs.swap (rhs);

View File

@@ -23,8 +23,8 @@
#include <ripple/beast/container/detail/aged_container_iterator.h>
#include <ripple/beast/container/detail/aged_associative_container.h>
#include <ripple/beast/container/aged_container.h>
#include <beast/clock/abstract_clock.h>
#include <beast/empty_base_optimization.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <beast/detail/empty_base_optimization.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/unordered_set.hpp>
#include <algorithm>
@@ -618,14 +618,14 @@ public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator= detail::aged_container_iterator <!IsMap,
using iterator= beast::detail::aged_container_iterator <!IsMap,
typename cont_type::iterator>;
using const_iterator = detail::aged_container_iterator <true,
using const_iterator = beast::detail::aged_container_iterator <true,
typename cont_type::iterator>;
using local_iterator = detail::aged_container_iterator <!IsMap,
using local_iterator = beast::detail::aged_container_iterator <!IsMap,
typename cont_type::local_iterator>;
using const_local_iterator = detail::aged_container_iterator <true,
using const_local_iterator = beast::detail::aged_container_iterator <true,
typename cont_type::local_iterator>;
//--------------------------------------------------------------------------
@@ -642,13 +642,13 @@ public:
public:
// A set iterator (IsMap==false) is always const
// because the elements of a set are immutable.
using iterator = detail::aged_container_iterator <
using iterator = beast::detail::aged_container_iterator <
! IsMap, typename list_type::iterator>;
using const_iterator = detail::aged_container_iterator <
using const_iterator = beast::detail::aged_container_iterator <
true, typename list_type::iterator>;
using reverse_iterator = detail::aged_container_iterator <
using reverse_iterator = beast::detail::aged_container_iterator <
! IsMap, typename list_type::reverse_iterator>;
using const_reverse_iterator = detail::aged_container_iterator <
using const_reverse_iterator = beast::detail::aged_container_iterator <
true, typename list_type::reverse_iterator>;
iterator begin ()
@@ -1143,15 +1143,15 @@ public:
}
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <
beast::detail::aged_container_iterator <false, Iterator, Base>
erase (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos);
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
erase (detail::aged_container_iterator <
beast::detail::aged_container_iterator <false, Iterator, Base>
erase (beast::detail::aged_container_iterator <
is_const, Iterator, Base> first,
detail::aged_container_iterator <
beast::detail::aged_container_iterator <
is_const, Iterator, Base> last);
template <class K>
@@ -1164,7 +1164,7 @@ public:
template <bool is_const, class Iterator, class Base>
void
touch (detail::aged_container_iterator <
touch (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos)
{
touch (pos, clock().now());
@@ -1459,7 +1459,7 @@ private:
template <bool is_const, class Iterator, class Base>
void
touch (detail::aged_container_iterator <
touch (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos,
typename clock_type::time_point const& now)
{
@@ -2297,32 +2297,32 @@ emplace_hint (const_iterator /*hint*/, Args&&... args) ->
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
beast::detail::aged_container_iterator <false, Iterator, Base>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
erase (detail::aged_container_iterator <
erase (beast::detail::aged_container_iterator <
is_const, Iterator, Base> pos)
{
unlink_and_delete_element(&*((pos++).iterator()));
return detail::aged_container_iterator <
return beast::detail::aged_container_iterator <
false, Iterator, Base> (pos.iterator());
}
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Hash, class KeyEqual, class Allocator>
template <bool is_const, class Iterator, class Base>
detail::aged_container_iterator <false, Iterator, Base>
beast::detail::aged_container_iterator <false, Iterator, Base>
aged_unordered_container <IsMulti, IsMap, Key, T, Clock,
Hash, KeyEqual, Allocator>::
erase (detail::aged_container_iterator <
erase (beast::detail::aged_container_iterator <
is_const, Iterator, Base> first,
detail::aged_container_iterator <
beast::detail::aged_container_iterator <
is_const, Iterator, Base> last)
{
for (; first != last;)
unlink_and_delete_element(&*((first++).iterator()));
return detail::aged_container_iterator <
return beast::detail::aged_container_iterator <
false, Iterator, Base> (first.iterator());
}
@@ -2510,7 +2510,7 @@ insert_unchecked (value_type const& value) ->
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Hash, class KeyEqual, class Allocator>
struct is_aged_container <detail::aged_unordered_container <
struct is_aged_container <beast::detail::aged_unordered_container <
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>>
: std::true_type
{
@@ -2521,9 +2521,9 @@ struct is_aged_container <detail::aged_unordered_container <
template <bool IsMulti, bool IsMap, class Key, class T, class Clock,
class Hash, class KeyEqual, class Allocator>
void swap (
detail::aged_unordered_container <IsMulti, IsMap,
beast::detail::aged_unordered_container <IsMulti, IsMap,
Key, T, Clock, Hash, KeyEqual, Allocator>& lhs,
detail::aged_unordered_container <IsMulti, IsMap,
beast::detail::aged_unordered_container <IsMulti, IsMap,
Key, T, Clock, Hash, KeyEqual, Allocator>& rhs) noexcept
{
lhs.swap (rhs);
@@ -2533,7 +2533,7 @@ void swap (
template <bool IsMulti, bool IsMap, class Key, class T,
class Clock, class Hash, class KeyEqual, class Allocator,
class Rep, class Period>
std::size_t expire (detail::aged_unordered_container <
std::size_t expire (beast::detail::aged_unordered_container <
IsMulti, IsMap, Key, T, Clock, Hash, KeyEqual, Allocator>& c,
std::chrono::duration <Rep, Period> const& age) noexcept
{

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#include <beast/clock/manual_clock.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/clock/manual_clock.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/container/aged_set.h>
#include <ripple/beast/container/aged_map.h>

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#include <beast/unit_test/suite.h>
#include <beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/xor_shift_engine.h>
namespace beast {

View File

@@ -73,7 +73,7 @@ class ListIterator : public std::iterator <
std::bidirectional_iterator_tag, std::size_t>
{
public:
using value_type = typename detail::CopyConst <
using value_type = typename beast::detail::CopyConst <
N, typename N::value_type>::type;
using pointer = value_type*;
using reference = value_type&;

View File

@@ -257,7 +257,7 @@ static double getStartupTime()
{
StaticInitializer ()
{
when = detail::monotonicCurrentTimeInSeconds();
when = beast::detail::monotonicCurrentTimeInSeconds();
}
double when;

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/core/LexicalCast.h>
#include <algorithm>

View File

@@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_MAC_FACADE_H_INCLUDED
#define BEAST_CRYPTO_MAC_FACADE_H_INCLUDED
#include <ripple/beast/crypto/secure_erase.h>
#include <ripple/beast/hash/endian.h>
#include <type_traits>
#include <array>
namespace beast {
namespace detail {
// Message Authentication Code (MAC) facade
template <class Context, bool Secure>
class mac_facade
{
private:
Context ctx_;
public:
static beast::endian const endian =
beast::endian::native;
static std::size_t const digest_size =
Context::digest_size;
using result_type =
std::array<std::uint8_t, digest_size>;
mac_facade() noexcept
{
init(ctx_);
}
~mac_facade()
{
erase(std::integral_constant<
bool, Secure>{});
}
void
operator()(void const* data,
std::size_t size) noexcept
{
update(ctx_, data, size);
}
explicit
operator result_type() noexcept
{
result_type digest;
finish(ctx_, &digest[0]);
return digest;
}
private:
inline
void
erase (std::false_type) noexcept
{
}
inline
void
erase (std::true_type) noexcept
{
secure_erase(&ctx_, sizeof(ctx_));
}
};
} // detail
} // beast
#endif

View File

@@ -0,0 +1,429 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_RIPEMD_CONTEXT_H_INCLUDED
#define BEAST_CRYPTO_RIPEMD_CONTEXT_H_INCLUDED
#include <array>
#include <cstdint>
#include <cstring>
namespace beast {
namespace detail {
// Based on
// https://code.google.com/p/blockchain/source/browse/trunk/RIPEMD160.cpp
/*
Copyright (c) Katholieke Universiteit Leuven
1996 All Rights Reserved
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// This implementation has been modified from the
// original. It has been updated for C++11.
struct ripemd160_context
{
static unsigned int const block_size = 64;
static unsigned int const digest_size = 20;
unsigned int tot_len;
unsigned int len;
unsigned char block[256];
std::uint32_t h[5];
};
// ROL(x, n) cyclically rotates x over n bits to the left
// x must be of an unsigned 32 bits type and 0 <= n < 32.
#define BEAST_RIPEMD_ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// the five basic functions F(), G() and H()
#define BEAST_RIPEMD_F(x, y, z) ((x) ^ (y) ^ (z))
#define BEAST_RIPEMD_G(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define BEAST_RIPEMD_H(x, y, z) (((x) | ~(y)) ^ (z))
#define BEAST_RIPEMD_I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define BEAST_RIPEMD_J(x, y, z) ((x) ^ ((y) | ~(z)))
// the ten basic operations FF() through III()
#define BEAST_RIPEMD_FF(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_F((b), (c), (d)) + (x); \
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_GG(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_G((b), (c), (d)) + (x) + 0x5a827999UL; \
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_HH(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_II(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_JJ(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_FFF(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_F((b), (c), (d)) + (x); \
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_GGG(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_HHH(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_III(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
#define BEAST_RIPEMD_JJJ(a, b, c, d, e, x, s) { \
(a) += BEAST_RIPEMD_J((b), (c), (d)) + (x) + 0x50a28be6UL;\
(a) = BEAST_RIPEMD_ROL((a), (s)) + (e); \
(c) = BEAST_RIPEMD_ROL((c), 10); }
template <class = void>
void ripemd_load (std::array<std::uint32_t, 16>& X,
unsigned char const* p)
{
for(int i = 0; i < 16; ++i)
{
X[i] =
((std::uint32_t) *((p)+3) << 24) |
((std::uint32_t) *((p)+2) << 16) |
((std::uint32_t) *((p)+1) << 8) |
((std::uint32_t) * (p));
p += 4;
}
}
template <class = void>
void ripemd_compress (ripemd160_context& ctx,
std::array<std::uint32_t, 16>& X) noexcept
{
std::uint32_t aa = ctx.h[0];
std::uint32_t bb = ctx.h[1];
std::uint32_t cc = ctx.h[2];
std::uint32_t dd = ctx.h[3];
std::uint32_t ee = ctx.h[4];
std::uint32_t aaa = ctx.h[0];
std::uint32_t bbb = ctx.h[1];
std::uint32_t ccc = ctx.h[2];
std::uint32_t ddd = ctx.h[3];
std::uint32_t eee = ctx.h[4];
// round 1
BEAST_RIPEMD_FF(aa, bb, cc, dd, ee, X[ 0], 11);
BEAST_RIPEMD_FF(ee, aa, bb, cc, dd, X[ 1], 14);
BEAST_RIPEMD_FF(dd, ee, aa, bb, cc, X[ 2], 15);
BEAST_RIPEMD_FF(cc, dd, ee, aa, bb, X[ 3], 12);
BEAST_RIPEMD_FF(bb, cc, dd, ee, aa, X[ 4], 5);
BEAST_RIPEMD_FF(aa, bb, cc, dd, ee, X[ 5], 8);
BEAST_RIPEMD_FF(ee, aa, bb, cc, dd, X[ 6], 7);
BEAST_RIPEMD_FF(dd, ee, aa, bb, cc, X[ 7], 9);
BEAST_RIPEMD_FF(cc, dd, ee, aa, bb, X[ 8], 11);
BEAST_RIPEMD_FF(bb, cc, dd, ee, aa, X[ 9], 13);
BEAST_RIPEMD_FF(aa, bb, cc, dd, ee, X[10], 14);
BEAST_RIPEMD_FF(ee, aa, bb, cc, dd, X[11], 15);
BEAST_RIPEMD_FF(dd, ee, aa, bb, cc, X[12], 6);
BEAST_RIPEMD_FF(cc, dd, ee, aa, bb, X[13], 7);
BEAST_RIPEMD_FF(bb, cc, dd, ee, aa, X[14], 9);
BEAST_RIPEMD_FF(aa, bb, cc, dd, ee, X[15], 8);
// round 2
BEAST_RIPEMD_GG(ee, aa, bb, cc, dd, X[ 7], 7);
BEAST_RIPEMD_GG(dd, ee, aa, bb, cc, X[ 4], 6);
BEAST_RIPEMD_GG(cc, dd, ee, aa, bb, X[13], 8);
BEAST_RIPEMD_GG(bb, cc, dd, ee, aa, X[ 1], 13);
BEAST_RIPEMD_GG(aa, bb, cc, dd, ee, X[10], 11);
BEAST_RIPEMD_GG(ee, aa, bb, cc, dd, X[ 6], 9);
BEAST_RIPEMD_GG(dd, ee, aa, bb, cc, X[15], 7);
BEAST_RIPEMD_GG(cc, dd, ee, aa, bb, X[ 3], 15);
BEAST_RIPEMD_GG(bb, cc, dd, ee, aa, X[12], 7);
BEAST_RIPEMD_GG(aa, bb, cc, dd, ee, X[ 0], 12);
BEAST_RIPEMD_GG(ee, aa, bb, cc, dd, X[ 9], 15);
BEAST_RIPEMD_GG(dd, ee, aa, bb, cc, X[ 5], 9);
BEAST_RIPEMD_GG(cc, dd, ee, aa, bb, X[ 2], 11);
BEAST_RIPEMD_GG(bb, cc, dd, ee, aa, X[14], 7);
BEAST_RIPEMD_GG(aa, bb, cc, dd, ee, X[11], 13);
BEAST_RIPEMD_GG(ee, aa, bb, cc, dd, X[ 8], 12);
// round 3
BEAST_RIPEMD_HH(dd, ee, aa, bb, cc, X[ 3], 11);
BEAST_RIPEMD_HH(cc, dd, ee, aa, bb, X[10], 13);
BEAST_RIPEMD_HH(bb, cc, dd, ee, aa, X[14], 6);
BEAST_RIPEMD_HH(aa, bb, cc, dd, ee, X[ 4], 7);
BEAST_RIPEMD_HH(ee, aa, bb, cc, dd, X[ 9], 14);
BEAST_RIPEMD_HH(dd, ee, aa, bb, cc, X[15], 9);
BEAST_RIPEMD_HH(cc, dd, ee, aa, bb, X[ 8], 13);
BEAST_RIPEMD_HH(bb, cc, dd, ee, aa, X[ 1], 15);
BEAST_RIPEMD_HH(aa, bb, cc, dd, ee, X[ 2], 14);
BEAST_RIPEMD_HH(ee, aa, bb, cc, dd, X[ 7], 8);
BEAST_RIPEMD_HH(dd, ee, aa, bb, cc, X[ 0], 13);
BEAST_RIPEMD_HH(cc, dd, ee, aa, bb, X[ 6], 6);
BEAST_RIPEMD_HH(bb, cc, dd, ee, aa, X[13], 5);
BEAST_RIPEMD_HH(aa, bb, cc, dd, ee, X[11], 12);
BEAST_RIPEMD_HH(ee, aa, bb, cc, dd, X[ 5], 7);
BEAST_RIPEMD_HH(dd, ee, aa, bb, cc, X[12], 5);
// round 4
BEAST_RIPEMD_II(cc, dd, ee, aa, bb, X[ 1], 11);
BEAST_RIPEMD_II(bb, cc, dd, ee, aa, X[ 9], 12);
BEAST_RIPEMD_II(aa, bb, cc, dd, ee, X[11], 14);
BEAST_RIPEMD_II(ee, aa, bb, cc, dd, X[10], 15);
BEAST_RIPEMD_II(dd, ee, aa, bb, cc, X[ 0], 14);
BEAST_RIPEMD_II(cc, dd, ee, aa, bb, X[ 8], 15);
BEAST_RIPEMD_II(bb, cc, dd, ee, aa, X[12], 9);
BEAST_RIPEMD_II(aa, bb, cc, dd, ee, X[ 4], 8);
BEAST_RIPEMD_II(ee, aa, bb, cc, dd, X[13], 9);
BEAST_RIPEMD_II(dd, ee, aa, bb, cc, X[ 3], 14);
BEAST_RIPEMD_II(cc, dd, ee, aa, bb, X[ 7], 5);
BEAST_RIPEMD_II(bb, cc, dd, ee, aa, X[15], 6);
BEAST_RIPEMD_II(aa, bb, cc, dd, ee, X[14], 8);
BEAST_RIPEMD_II(ee, aa, bb, cc, dd, X[ 5], 6);
BEAST_RIPEMD_II(dd, ee, aa, bb, cc, X[ 6], 5);
BEAST_RIPEMD_II(cc, dd, ee, aa, bb, X[ 2], 12);
// round 5
BEAST_RIPEMD_JJ(bb, cc, dd, ee, aa, X[ 4], 9);
BEAST_RIPEMD_JJ(aa, bb, cc, dd, ee, X[ 0], 15);
BEAST_RIPEMD_JJ(ee, aa, bb, cc, dd, X[ 5], 5);
BEAST_RIPEMD_JJ(dd, ee, aa, bb, cc, X[ 9], 11);
BEAST_RIPEMD_JJ(cc, dd, ee, aa, bb, X[ 7], 6);
BEAST_RIPEMD_JJ(bb, cc, dd, ee, aa, X[12], 8);
BEAST_RIPEMD_JJ(aa, bb, cc, dd, ee, X[ 2], 13);
BEAST_RIPEMD_JJ(ee, aa, bb, cc, dd, X[10], 12);
BEAST_RIPEMD_JJ(dd, ee, aa, bb, cc, X[14], 5);
BEAST_RIPEMD_JJ(cc, dd, ee, aa, bb, X[ 1], 12);
BEAST_RIPEMD_JJ(bb, cc, dd, ee, aa, X[ 3], 13);
BEAST_RIPEMD_JJ(aa, bb, cc, dd, ee, X[ 8], 14);
BEAST_RIPEMD_JJ(ee, aa, bb, cc, dd, X[11], 11);
BEAST_RIPEMD_JJ(dd, ee, aa, bb, cc, X[ 6], 8);
BEAST_RIPEMD_JJ(cc, dd, ee, aa, bb, X[15], 5);
BEAST_RIPEMD_JJ(bb, cc, dd, ee, aa, X[13], 6);
// parallel round 1
BEAST_RIPEMD_JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8);
BEAST_RIPEMD_JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9);
BEAST_RIPEMD_JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9);
BEAST_RIPEMD_JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
BEAST_RIPEMD_JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
BEAST_RIPEMD_JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
BEAST_RIPEMD_JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15);
BEAST_RIPEMD_JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5);
BEAST_RIPEMD_JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7);
BEAST_RIPEMD_JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7);
BEAST_RIPEMD_JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8);
BEAST_RIPEMD_JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
BEAST_RIPEMD_JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
BEAST_RIPEMD_JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14);
BEAST_RIPEMD_JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
BEAST_RIPEMD_JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6);
// parallel round 2
BEAST_RIPEMD_III(eee, aaa, bbb, ccc, ddd, X[ 6], 9);
BEAST_RIPEMD_III(ddd, eee, aaa, bbb, ccc, X[11], 13);
BEAST_RIPEMD_III(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
BEAST_RIPEMD_III(bbb, ccc, ddd, eee, aaa, X[ 7], 7);
BEAST_RIPEMD_III(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
BEAST_RIPEMD_III(eee, aaa, bbb, ccc, ddd, X[13], 8);
BEAST_RIPEMD_III(ddd, eee, aaa, bbb, ccc, X[ 5], 9);
BEAST_RIPEMD_III(ccc, ddd, eee, aaa, bbb, X[10], 11);
BEAST_RIPEMD_III(bbb, ccc, ddd, eee, aaa, X[14], 7);
BEAST_RIPEMD_III(aaa, bbb, ccc, ddd, eee, X[15], 7);
BEAST_RIPEMD_III(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
BEAST_RIPEMD_III(ddd, eee, aaa, bbb, ccc, X[12], 7);
BEAST_RIPEMD_III(ccc, ddd, eee, aaa, bbb, X[ 4], 6);
BEAST_RIPEMD_III(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
BEAST_RIPEMD_III(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
BEAST_RIPEMD_III(eee, aaa, bbb, ccc, ddd, X[ 2], 11);
// parallel round 3
BEAST_RIPEMD_HHH(ddd, eee, aaa, bbb, ccc, X[15], 9);
BEAST_RIPEMD_HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7);
BEAST_RIPEMD_HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
BEAST_RIPEMD_HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
BEAST_RIPEMD_HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8);
BEAST_RIPEMD_HHH(ddd, eee, aaa, bbb, ccc, X[14], 6);
BEAST_RIPEMD_HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6);
BEAST_RIPEMD_HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
BEAST_RIPEMD_HHH(aaa, bbb, ccc, ddd, eee, X[11], 12);
BEAST_RIPEMD_HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
BEAST_RIPEMD_HHH(ddd, eee, aaa, bbb, ccc, X[12], 5);
BEAST_RIPEMD_HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
BEAST_RIPEMD_HHH(bbb, ccc, ddd, eee, aaa, X[10], 13);
BEAST_RIPEMD_HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
BEAST_RIPEMD_HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7);
BEAST_RIPEMD_HHH(ddd, eee, aaa, bbb, ccc, X[13], 5);
// parallel round 4
BEAST_RIPEMD_GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
BEAST_RIPEMD_GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5);
BEAST_RIPEMD_GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8);
BEAST_RIPEMD_GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
BEAST_RIPEMD_GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
BEAST_RIPEMD_GGG(ccc, ddd, eee, aaa, bbb, X[11], 14);
BEAST_RIPEMD_GGG(bbb, ccc, ddd, eee, aaa, X[15], 6);
BEAST_RIPEMD_GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
BEAST_RIPEMD_GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6);
BEAST_RIPEMD_GGG(ddd, eee, aaa, bbb, ccc, X[12], 9);
BEAST_RIPEMD_GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
BEAST_RIPEMD_GGG(bbb, ccc, ddd, eee, aaa, X[13], 9);
BEAST_RIPEMD_GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
BEAST_RIPEMD_GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5);
BEAST_RIPEMD_GGG(ddd, eee, aaa, bbb, ccc, X[10], 15);
BEAST_RIPEMD_GGG(ccc, ddd, eee, aaa, bbb, X[14], 8);
// parallel round 5
BEAST_RIPEMD_FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8);
BEAST_RIPEMD_FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5);
BEAST_RIPEMD_FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12);
BEAST_RIPEMD_FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9);
BEAST_RIPEMD_FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
BEAST_RIPEMD_FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5);
BEAST_RIPEMD_FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
BEAST_RIPEMD_FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6);
BEAST_RIPEMD_FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8);
BEAST_RIPEMD_FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
BEAST_RIPEMD_FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6);
BEAST_RIPEMD_FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5);
BEAST_RIPEMD_FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
BEAST_RIPEMD_FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
BEAST_RIPEMD_FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
BEAST_RIPEMD_FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11);
// combine results
ddd += cc + ctx.h[1]; // final result for h[0]
ctx.h[1] = ctx.h[2] + dd + eee;
ctx.h[2] = ctx.h[3] + ee + aaa;
ctx.h[3] = ctx.h[4] + aa + bbb;
ctx.h[4] = ctx.h[0] + bb + ccc;
ctx.h[0] = ddd;
}
template <class = void>
void init (ripemd160_context& ctx) noexcept
{
ctx.len = 0;
ctx.tot_len = 0;
ctx.h[0] = 0x67452301UL;
ctx.h[1] = 0xefcdab89UL;
ctx.h[2] = 0x98badcfeUL;
ctx.h[3] = 0x10325476UL;
ctx.h[4] = 0xc3d2e1f0UL;
}
template <class = void>
void update (ripemd160_context& ctx,
void const* message, std::size_t size) noexcept
{
auto const pm = reinterpret_cast<
unsigned char const*>(message);
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = ripemd160_context::block_size - ctx.len;
rem_len = size < tmp_len ? size : tmp_len;
std::memcpy(&ctx.block[ctx.len], pm, rem_len);
if (ctx.len + size < ripemd160_context::block_size) {
ctx.len += size;
return;
}
new_len = size - rem_len;
block_nb = new_len / ripemd160_context::block_size;
shifted_message = pm + rem_len;
std::array<std::uint32_t, 16> X;
ripemd_load(X, ctx.block);
ripemd_compress(ctx, X);
for (int i = 0; i < block_nb; ++i)
{
ripemd_load(X, shifted_message +
i * ripemd160_context::block_size);
ripemd_compress(ctx, X);
}
rem_len = new_len % ripemd160_context::block_size;
std::memcpy(ctx.block, &shifted_message[
block_nb * ripemd160_context::block_size],
rem_len);
ctx.len = rem_len;
ctx.tot_len += (block_nb + 1) *
ripemd160_context::block_size;
}
template <class = void>
void finish (ripemd160_context& ctx,
void* digest) noexcept
{
std::array<std::uint32_t, 16> X;
X.fill(0);
// put leftovers into X
auto p = &ctx.block[0];
// uint8_t i goes into word X[i div 4] at pos. 8*(i mod 4)
for (int i = 0; i < ctx.len; ++i)
X[i >> 2] ^= (std::uint32_t) *p++ << (8 * (i & 3));
ctx.tot_len += ctx.len;
// append the bit m_n == 1
X[(ctx.tot_len>>2)&15] ^=
(uint32_t)1 << (8*(ctx.tot_len&3) + 7);
// length goes to next block?
if ((ctx.tot_len & 63) > 55)
{
ripemd_compress(ctx, X);
X.fill(0);
}
// append length in bits*/
X[14] = ctx.tot_len << 3;
X[15] = (ctx.tot_len >> 29) | (0 << 3);
ripemd_compress(ctx, X);
std::uint8_t* pd = reinterpret_cast<
std::uint8_t*>(digest);
for (std::uint32_t i = 0; i < 20; i += 4)
{
pd[i] = (std::uint8_t)(ctx.h[i>>2]); // implicit cast to uint8_t
pd[i+1] = (std::uint8_t)(ctx.h[i>>2] >> 8); // extracts the 8 least
pd[i+2] = (std::uint8_t)(ctx.h[i>>2] >> 16); // significant bits.
pd[i+3] = (std::uint8_t)(ctx.h[i>>2] >> 24);
}
}
} // detail
} // beast
#endif

View File

@@ -0,0 +1,428 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_SHA512_CONTEXT_H_INCLUDED
#define BEAST_CRYPTO_SHA512_CONTEXT_H_INCLUDED
#include <cstdint>
#include <cstring>
namespace beast {
namespace detail {
// Based on https://github.com/ogay/sha2
// This implementation has been modified from the
// original. It has been updated for C++11.
/*
* Updated to C++, zedwood.com 2012
* Based on Olivier Gay's version
* See Modified BSD License below:
*
* FIPS 180-2 SHA-224/256/384/512 implementation
* Issue date: 04/30/2005
* http://www.ouah.org/ogay/sha2/
*
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
struct sha256_context
{
static unsigned int const block_size = 64;
static unsigned int const digest_size = 32;
unsigned int tot_len;
unsigned int len;
unsigned char block[2 * block_size];
std::uint32_t h[8];
};
struct sha512_context
{
static unsigned int const block_size = 128;
static unsigned int const digest_size = 64;
unsigned int tot_len;
unsigned int len;
unsigned char block[2 * block_size];
std::uint64_t h[8];
};
#define BEAST_SHA2_SHFR(x, n) (x >> n)
#define BEAST_SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define BEAST_SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define BEAST_SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define BEAST_SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define BEAST_SHA256_F1(x) (BEAST_SHA2_ROTR(x, 2) ^ BEAST_SHA2_ROTR(x, 13) ^ BEAST_SHA2_ROTR(x, 22))
#define BEAST_SHA256_F2(x) (BEAST_SHA2_ROTR(x, 6) ^ BEAST_SHA2_ROTR(x, 11) ^ BEAST_SHA2_ROTR(x, 25))
#define BEAST_SHA256_F3(x) (BEAST_SHA2_ROTR(x, 7) ^ BEAST_SHA2_ROTR(x, 18) ^ BEAST_SHA2_SHFR(x, 3))
#define BEAST_SHA256_F4(x) (BEAST_SHA2_ROTR(x, 17) ^ BEAST_SHA2_ROTR(x, 19) ^ BEAST_SHA2_SHFR(x, 10))
#define BEAST_SHA512_F1(x) (BEAST_SHA2_ROTR(x, 28) ^ BEAST_SHA2_ROTR(x, 34) ^ BEAST_SHA2_ROTR(x, 39))
#define BEAST_SHA512_F2(x) (BEAST_SHA2_ROTR(x, 14) ^ BEAST_SHA2_ROTR(x, 18) ^ BEAST_SHA2_ROTR(x, 41))
#define BEAST_SHA512_F3(x) (BEAST_SHA2_ROTR(x, 1) ^ BEAST_SHA2_ROTR(x, 8) ^ BEAST_SHA2_SHFR(x, 7))
#define BEAST_SHA512_F4(x) (BEAST_SHA2_ROTR(x, 19) ^ BEAST_SHA2_ROTR(x, 61) ^ BEAST_SHA2_SHFR(x, 6))
#define BEAST_SHA2_PACK32(str, x) \
{ \
*(x) = \
((std::uint32_t) *((str) + 3) ) \
| ((std::uint32_t) *((str) + 2) << 8) \
| ((std::uint32_t) *((str) + 1) << 16) \
| ((std::uint32_t) *((str) + 0) << 24); \
}
#define BEAST_SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (std::uint8_t) ((x) ); \
*((str) + 2) = (std::uint8_t) ((x) >> 8); \
*((str) + 1) = (std::uint8_t) ((x) >> 16); \
*((str) + 0) = (std::uint8_t) ((x) >> 24); \
}
#define BEAST_SHA2_PACK64(str, x) \
{ \
*(x) = \
((std::uint64_t) *((str) + 7) ) \
| ((std::uint64_t) *((str) + 6) << 8) \
| ((std::uint64_t) *((str) + 5) << 16) \
| ((std::uint64_t) *((str) + 4) << 24) \
| ((std::uint64_t) *((str) + 3) << 32) \
| ((std::uint64_t) *((str) + 2) << 40) \
| ((std::uint64_t) *((str) + 1) << 48) \
| ((std::uint64_t) *((str) + 0) << 56); \
}
#define BEAST_SHA2_UNPACK64(x, str) \
{ \
*((str) + 7) = (std::uint8_t) ((x) ); \
*((str) + 6) = (std::uint8_t) ((x) >> 8); \
*((str) + 5) = (std::uint8_t) ((x) >> 16); \
*((str) + 4) = (std::uint8_t) ((x) >> 24); \
*((str) + 3) = (std::uint8_t) ((x) >> 32); \
*((str) + 2) = (std::uint8_t) ((x) >> 40); \
*((str) + 1) = (std::uint8_t) ((x) >> 48); \
*((str) + 0) = (std::uint8_t) ((x) >> 56); \
}
//------------------------------------------------------------------------------
// SHA256
template <class = void>
void sha256_transform (sha256_context& ctx,
unsigned char const* message,
unsigned int block_nb) noexcept
{
static unsigned long long const K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
std::uint32_t w[64];
std::uint32_t wv[8];
std::uint32_t t1, t2;
unsigned char const* sub_block;
int i, j;
for (i = 0; i < (int) block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++)
BEAST_SHA2_PACK32(&sub_block[j << 2], &w[j]);
for (j = 16; j < 64; j++)
w[j] = BEAST_SHA256_F4(
w[j - 2]) + w[j - 7] +
BEAST_SHA256_F3(w[j - 15]) +
w[j - 16];
for (j = 0; j < 8; j++)
wv[j] = ctx.h[j];
for (j = 0; j < 64; j++) {
t1 = wv[7] + BEAST_SHA256_F2(wv[4]) +
BEAST_SHA2_CH(wv[4], wv[5], wv[6]) +
K[j] + w[j];
t2 = BEAST_SHA256_F1(wv[0]) +
BEAST_SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++)
ctx.h[j] += wv[j];
}
}
template <class = void>
void init (sha256_context& ctx) noexcept
{
ctx.len = 0;
ctx.tot_len = 0;
ctx.h[0] = 0x6a09e667;
ctx.h[1] = 0xbb67ae85;
ctx.h[2] = 0x3c6ef372;
ctx.h[3] = 0xa54ff53a;
ctx.h[4] = 0x510e527f;
ctx.h[5] = 0x9b05688c;
ctx.h[6] = 0x1f83d9ab;
ctx.h[7] = 0x5be0cd19;
}
template <class = void>
void update (sha256_context& ctx,
void const* message, std::size_t size) noexcept
{
auto const pm = reinterpret_cast<
unsigned char const*>(message);
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = sha256_context::block_size - ctx.len;
rem_len = size < tmp_len ? size : tmp_len;
std::memcpy(&ctx.block[ctx.len], pm, rem_len);
if (ctx.len + size < sha256_context::block_size) {
ctx.len += size;
return;
}
new_len = size - rem_len;
block_nb = new_len / sha256_context::block_size;
shifted_message = pm + rem_len;
sha256_transform(ctx, ctx.block, 1);
sha256_transform(ctx, shifted_message, block_nb);
rem_len = new_len % sha256_context::block_size;
std::memcpy(ctx.block, &shifted_message[
block_nb << 6], rem_len);
ctx.len = rem_len;
ctx.tot_len += (block_nb + 1) << 6;
}
template <class = void>
void finish (sha256_context& ctx,
void* digest) noexcept
{
auto const pd = reinterpret_cast<
unsigned char*>(digest);
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((sha256_context::block_size - 9) <
(ctx.len % sha256_context::block_size)));
len_b = (ctx.tot_len + ctx.len) << 3;
pm_len = block_nb << 6;
std::memset(ctx.block + ctx.len, 0, pm_len - ctx.len);
ctx.block[ctx.len] = 0x80;
BEAST_SHA2_UNPACK32(len_b, ctx.block + pm_len - 4);
sha256_transform(ctx, ctx.block, block_nb);
for (i = 0 ; i < 8; i++)
BEAST_SHA2_UNPACK32(ctx.h[i], &pd[i << 2]);
}
//------------------------------------------------------------------------------
// SHA512
template <class = void>
void sha512_transform (sha512_context& ctx,
unsigned char const* message,
unsigned int block_nb) noexcept
{
static unsigned long long const K[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
std::uint64_t w[80];
std::uint64_t wv[8];
std::uint64_t t1, t2;
unsigned char const* sub_block;
int i, j;
for (i = 0; i < (int) block_nb; i++)
{
sub_block = message + (i << 7);
for (j = 0; j < 16; j++)
BEAST_SHA2_PACK64(&sub_block[j << 3], &w[j]);
for (j = 16; j < 80; j++)
w[j] = BEAST_SHA512_F4(
w[j - 2]) + w[j - 7] +
BEAST_SHA512_F3(w[j - 15]) +
w[j - 16];
for (j = 0; j < 8; j++)
wv[j] = ctx.h[j];
for (j = 0; j < 80; j++) {
t1 = wv[7] + BEAST_SHA512_F2(wv[4]) +
BEAST_SHA2_CH(wv[4], wv[5], wv[6]) +
K[j] + w[j];
t2 = BEAST_SHA512_F1(wv[0]) +
BEAST_SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++)
ctx.h[j] += wv[j];
}
}
template <class = void>
void init (sha512_context& ctx) noexcept
{
ctx.len = 0;
ctx.tot_len = 0;
ctx.h[0] = 0x6a09e667f3bcc908ULL;
ctx.h[1] = 0xbb67ae8584caa73bULL;
ctx.h[2] = 0x3c6ef372fe94f82bULL;
ctx.h[3] = 0xa54ff53a5f1d36f1ULL;
ctx.h[4] = 0x510e527fade682d1ULL;
ctx.h[5] = 0x9b05688c2b3e6c1fULL;
ctx.h[6] = 0x1f83d9abfb41bd6bULL;
ctx.h[7] = 0x5be0cd19137e2179ULL;
}
template <class = void>
void update (sha512_context& ctx,
void const* message, std::size_t size) noexcept
{
auto const pm = reinterpret_cast<
unsigned char const*>(message);
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = sha512_context::block_size - ctx.len;
rem_len = size < tmp_len ? size : tmp_len;
std::memcpy(&ctx.block[ctx.len], pm, rem_len);
if (ctx.len + size < sha512_context::block_size) {
ctx.len += size;
return;
}
new_len = size - rem_len;
block_nb = new_len / sha512_context::block_size;
shifted_message = pm + rem_len;
sha512_transform(ctx, ctx.block, 1);
sha512_transform(ctx, shifted_message, block_nb);
rem_len = new_len % sha512_context::block_size;
std::memcpy(ctx.block, &shifted_message[
block_nb << 7], rem_len);
ctx.len = rem_len;
ctx.tot_len += (block_nb + 1) << 7;
}
template <class = void>
void finish (sha512_context& ctx,
void* digest) noexcept
{
auto const pd = reinterpret_cast<
unsigned char*>(digest);
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((sha512_context::block_size - 17) <
(ctx.len % sha512_context::block_size));
len_b = (ctx.tot_len + ctx.len) << 3;
pm_len = block_nb << 7;
std::memset(ctx.block + ctx.len, 0, pm_len - ctx.len);
ctx.block[ctx.len] = 0x80;
BEAST_SHA2_UNPACK32(len_b, ctx.block + pm_len - 4);
sha512_transform(ctx, ctx.block, block_nb);
for (i = 0 ; i < 8; i++)
BEAST_SHA2_UNPACK64(ctx.h[i], &pd[i << 3]);
}
} // detail
} // beast
#endif

View File

@@ -0,0 +1,37 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_RIPEMD_H_INCLUDED
#define BEAST_CRYPTO_RIPEMD_H_INCLUDED
#include <ripple/beast/crypto/detail/mac_facade.h>
#include <ripple/beast/crypto/detail/ripemd_context.h>
namespace beast {
using ripemd160_hasher = detail::mac_facade<
detail::ripemd160_context, false>;
// secure version
using ripemd160_hasher_s = detail::mac_facade<
detail::ripemd160_context, true>;
}
#endif

View File

@@ -0,0 +1,87 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_SECURE_ERASE_H_INCLUDED
#define BEAST_CRYPTO_SECURE_ERASE_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <new>
namespace beast {
namespace detail {
class secure_erase_impl
{
private:
struct base
{
virtual void operator()(
void* dest, std::size_t bytes) const = 0;
};
struct impl : base
{
void operator()(
void* dest, std::size_t bytes) const override
{
char volatile* volatile p =
const_cast<volatile char*>(
reinterpret_cast<char*>(dest));
if (bytes == 0)
return;
do
{
*p = 0;
}
while(*p++ == 0 && --bytes);
}
};
char buf_[sizeof(impl)];
base& erase_;
public:
secure_erase_impl()
: erase_(*new(buf_) impl)
{
}
void operator()(
void* dest, std::size_t bytes) const
{
return erase_(dest, bytes);
}
};
}
/** Guaranteed to fill memory with zeroes */
template <class = void>
void
secure_erase (void* dest, std::size_t bytes)
{
static detail::secure_erase_impl const erase;
erase(dest, bytes);
}
}
#endif

View File

@@ -0,0 +1,44 @@
//------------------------------------------------------------------------------
/*
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_CRYPTO_SHA2_H_INCLUDED
#define BEAST_CRYPTO_SHA2_H_INCLUDED
#include <ripple/beast/crypto/detail/mac_facade.h>
#include <ripple/beast/crypto/detail/sha2_context.h>
namespace beast {
using sha256_hasher = detail::mac_facade<
detail::sha256_context, false>;
// secure version
using sha256_hasher_s = detail::mac_facade<
detail::sha256_context, true>;
using sha512_hasher = detail::mac_facade<
detail::sha512_context, false>;
// secure version
using sha512_hasher_s = detail::mac_facade<
detail::sha512_context, true>;
}
#endif

View File

@@ -0,0 +1,56 @@
//------------------------------------------------------------------------------
/*
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_CXX17_TYPE_TRAITS_H_INCLUDED
#define BEAST_CXX17_TYPE_TRAITS_H_INCLUDED
#include <tuple>
#include <type_traits>
#include <utility>
namespace std {
#ifndef _MSC_VER
template<class...>
using void_t = void;
template<bool B>
using bool_constant = std::integral_constant<bool, B>;
#endif
// Ideas from Howard Hinnant
//
// Specializations of is_constructible for pair and tuple which
// work around an apparent defect in the standard that causes well
// formed expressions involving pairs or tuples of non default-constructible
// types to generate compile errors.
//
template <class T, class U>
struct is_constructible <pair <T, U>>
: integral_constant <bool,
is_default_constructible <T>::value &&
is_default_constructible <U>::value>
{
};
} // std
#endif

View File

@@ -0,0 +1,465 @@
//------------------------------------------------------------------------------
/*
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_DEPRECATED_HTTP_H
#define BEAST_DEPRECATED_HTTP_H
#include <beast/http/method.hpp>
#include <beast/http/headers.hpp>
#include <beast/http/basic_parser.hpp>
#include <beast/http/detail/writes.hpp>
#include <beast/detail/ci_char_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <cctype>
#include <cstdint>
#include <functional>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <utility>
namespace beast {
namespace deprecated_http {
/** Container for the HTTP content-body. */
class body
{
private:
using buffer_type = boost::asio::streambuf;
// Hack: use unique_ptr because streambuf cant be moved
std::unique_ptr <buffer_type> buf_;
public:
using const_buffers_type = buffer_type::const_buffers_type;
body();
body (body&& other);
body& operator= (body&& other);
body (body const&) = delete;
body& operator= (body const&) = delete;
template <class = void>
void
clear();
void
write (void const* data, std::size_t bytes);
template <class ConstBufferSequence>
void
write (ConstBufferSequence const& buffers);
std::size_t
size() const;
const_buffers_type
data() const;
};
template <class = void>
std::string
to_string (body const& b)
{
std::string s;
auto const& data (b.data());
auto const n (boost::asio::buffer_size (data));
s.resize (n);
boost::asio::buffer_copy (
boost::asio::buffer (&s[0], n), data);
return s;
}
//------------------------------------------------------------------------------
inline
body::body()
: buf_ (std::make_unique <buffer_type>())
{
}
inline
body::body (body&& other)
: buf_ (std::move(other.buf_))
{
other.clear();
}
inline
body&
body::operator= (body&& other)
{
buf_ = std::move(other.buf_);
other.clear();
return *this;
}
template <class>
void
body::clear()
{
buf_ = std::make_unique <buffer_type>();
}
inline
void
body::write (void const* data, std::size_t bytes)
{
buf_->commit (boost::asio::buffer_copy (buf_->prepare (bytes),
boost::asio::const_buffers_1 (data, bytes)));
}
template <class ConstBufferSequence>
void
body::write (ConstBufferSequence const& buffers)
{
for (auto const& buffer : buffers)
write (boost::asio::buffer_cast <void const*> (buffer),
boost::asio::buffer_size (buffer));
}
inline
std::size_t
body::size() const
{
return buf_->size();
}
inline
auto
body::data() const
-> const_buffers_type
{
return buf_->data();
}
//------------------------------------------------------------------------------
inline
std::pair<int, int>
http_1_0()
{
return std::pair<int, int>(1, 0);
}
inline
std::pair<int, int>
http_1_1()
{
return std::pair<int, int>(1, 1);
}
class message
{
private:
bool request_;
// request
beast::http::method_t method_;
std::string url_;
// response
int status_;
std::string reason_;
// message
std::pair<int, int> version_;
bool keep_alive_;
bool upgrade_;
public:
~message() = default;
message (message const&) = default;
message (message&& other) = default;
message& operator= (message const&) = default;
message& operator= (message&& other) = default;
template <class = void>
message();
// Memberspace
beast::http::headers<std::allocator<char>> headers;
bool
request() const
{
return request_;
}
void
request (bool value)
{
request_ = value;
}
// Request
void
method (beast::http::method_t http_method)
{
method_ = http_method;
}
beast::http::method_t
method() const
{
return method_;
}
void
url (std::string const& s)
{
url_ = s;
}
std::string const&
url() const
{
return url_;
}
/** Returns `false` if this is not the last message.
When keep_alive returns `false`:
* Server roles respond with a "Connection: close" header.
* Client roles close the connection.
*/
bool
keep_alive() const
{
return keep_alive_;
}
/** Set the keep_alive setting. */
void
keep_alive (bool value)
{
keep_alive_ = value;
}
/** Returns `true` if this is an HTTP Upgrade message.
@note Upgrade messages have no content body.
*/
bool
upgrade() const
{
return upgrade_;
}
/** Set the upgrade setting. */
void
upgrade (bool value)
{
upgrade_ = value;
}
int
status() const
{
return status_;
}
void
status (int code)
{
status_ = code;
}
std::string const&
reason() const
{
return reason_;
}
void
reason (std::string const& text)
{
reason_ = text;
}
// Message
void
version (int major, int minor)
{
version_ = std::make_pair (major, minor);
}
void
version (std::pair<int, int> p)
{
version_ = p;
}
std::pair<int, int>
version() const
{
return version_;
}
};
//------------------------------------------------------------------------------
template <class>
message::message()
: request_ (true)
, method_ (beast::http::method_t::http_get)
, url_ ("/")
, status_ (200)
, version_ (1, 1)
, keep_alive_ (false)
, upgrade_ (false)
{
}
//------------------------------------------------------------------------------
template <class Streambuf>
void
write (Streambuf& stream, message const& m)
{
if (m.request())
{
http::detail::write (stream, to_string(m.method()));
http::detail::write (stream, " ");
http::detail::write (stream, m.url());
http::detail::write (stream, " HTTP/");
http::detail::write (stream, std::to_string(m.version().first));
http::detail::write (stream, ".");
http::detail::write (stream, std::to_string(m.version().second));
}
else
{
http::detail::write (stream, "HTTP/");
http::detail::write (stream, std::to_string(m.version().first));
http::detail::write (stream, ".");
http::detail::write (stream, std::to_string(m.version().second));
http::detail::write (stream, " ");
http::detail::write (stream, std::to_string(m.status()));
http::detail::write (stream, " ");
http::detail::write (stream, m.reason());
}
http::detail::write (stream, "\r\n");
write_fields(stream, m.headers);
http::detail::write (stream, "\r\n");
}
//------------------------------------------------------------------------------
class parser
: public beast::http::basic_parser<parser>
{
// friend class basic_parser<parser>;
message& m_;
std::function<void(void const*, std::size_t)> write_body_;
public:
parser(parser&&) = default;
parser(parser const&) = delete;
parser& operator=(parser&&) = delete;
parser& operator=(parser const&) = delete;
/** Construct a parser for HTTP request or response.
The headers plus request or status line are stored in message.
The content-body, if any, is passed as a series of calls to
the write_body function. Transfer encodings are applied before
any data is passed to the write_body function.
*/
parser(std::function<void(void const*, std::size_t)> write_body,
message& m, bool request)
: basic_parser(request)
, m_(m)
, write_body_(std::move(write_body))
{
m_.request(request);
}
parser(message& m, body& b, bool request)
: basic_parser(request)
, m_(m)
{
write_body_ = [&b](void const* data, std::size_t size)
{
b.write(data, size);
};
m_.request(request);
}
//private:
void
on_start()
{
}
void
on_headers_complete(error_code&)
{
}
bool
on_request(http::method_t method, std::string const& url,
int major, int minor, bool keep_alive, bool upgrade)
{
m_.method(method);
m_.url(url);
m_.version(major, minor);
m_.keep_alive(keep_alive);
m_.upgrade(upgrade);
return true;
}
bool
on_response(int status, std::string const& text,
int major, int minor, bool keep_alive, bool upgrade)
{
m_.status(status);
m_.reason(text);
m_.version(major, minor);
m_.keep_alive(keep_alive);
m_.upgrade(upgrade);
return true;
}
void
on_field(std::string const& field, std::string const& value)
{
m_.headers.insert(field, value);
}
void
on_body(void const* data, std::size_t bytes, error_code&)
{
write_body_(data, bytes);
}
void
on_complete()
{
}
};
} // deprecated_http
} // beast
#endif

View File

@@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_ENDIAN_H_INCLUDED
#define BEAST_HASH_ENDIAN_H_INCLUDED
namespace beast {
// endian provides answers to the following questions:
// 1. Is this system big or little endian?
// 2. Is the "desired endian" of some class or function the same as the
// native endian?
enum class endian
{
#ifdef _MSC_VER
big = 1,
little = 0,
native = little
#else
native = __BYTE_ORDER__,
little = __ORDER_LITTLE_ENDIAN__,
big = __ORDER_BIG_ENDIAN__
#endif
};
static_assert(endian::native == endian::little ||
endian::native == endian::big,
"endian::native shall be one of endian::little or endian::big");
static_assert(endian::big != endian::little,
"endian::big and endian::little shall have different values");
} // beast
#endif

View File

@@ -0,0 +1,70 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_FNV1A_H_INCLUDED
#define BEAST_HASH_FNV1A_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <type_traits>
namespace beast {
// See http://www.isthe.com/chongo/tech/comp/fnv/
//
class fnv1a
{
private:
std::uint64_t state_ = 14695981039346656037ULL;
public:
using result_type = std::size_t;
fnv1a() = default;
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
explicit
fnv1a (Seed seed)
{
append (&seed, sizeof(seed));
}
void
operator() (void const* key, std::size_t len) noexcept
{
unsigned char const* p =
static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
state_ = (state_ ^ *p) * 1099511628211ULL;
}
explicit
operator std::size_t() noexcept
{
return static_cast<std::size_t>(state_);
}
};
} // beast
#endif

View File

@@ -0,0 +1,516 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_HASH_APPEND_H_INCLUDED
#define BEAST_HASH_HASH_APPEND_H_INCLUDED
#include <ripple/beast/hash/endian.h>
#include <ripple/beast/hash/meta.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <system_error>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <type_traits>
#include <utility>
#include <vector>
namespace beast {
namespace detail {
template <class T>
/*constexpr*/
inline
void
reverse_bytes(T& t)
{
unsigned char* bytes = static_cast<unsigned char*>(std::memmove(std::addressof(t),
std::addressof(t),
sizeof(T)));
for (unsigned i = 0; i < sizeof(T)/2; ++i)
std::swap(bytes[i], bytes[sizeof(T)-1-i]);
}
template <class T>
/*constexpr*/
inline
void
maybe_reverse_bytes(T& t, std::false_type)
{
}
template <class T>
/*constexpr*/
inline
void
maybe_reverse_bytes(T& t, std::true_type)
{
reverse_bytes(t);
}
template <class T, class Hasher>
/*constexpr*/
inline
void
maybe_reverse_bytes(T& t, Hasher&)
{
maybe_reverse_bytes(t, std::integral_constant<bool,
Hasher::endian != endian::native>{});
}
} // detail
// is_uniquely_represented<T>
// A type T is contiguously hashable if for all combinations of two values of
// a type, say x and y, if x == y, then it must also be true that
// memcmp(addressof(x), addressof(y), sizeof(T)) == 0. I.e. if x == y,
// then x and y have the same bit pattern representation.
template <class T>
struct is_uniquely_represented
: public std::integral_constant<bool, std::is_integral<T>::value ||
std::is_enum<T>::value ||
std::is_pointer<T>::value>
{};
template <class T>
struct is_uniquely_represented<T const>
: public is_uniquely_represented<T>
{};
template <class T>
struct is_uniquely_represented<T volatile>
: public is_uniquely_represented<T>
{};
template <class T>
struct is_uniquely_represented<T const volatile>
: public is_uniquely_represented<T>
{};
// is_uniquely_represented<std::pair<T, U>>
template <class T, class U>
struct is_uniquely_represented<std::pair<T, U>>
: public std::integral_constant<bool, is_uniquely_represented<T>::value &&
is_uniquely_represented<U>::value &&
sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
{
};
// is_uniquely_represented<std::tuple<T...>>
template <class ...T>
struct is_uniquely_represented<std::tuple<T...>>
: public std::integral_constant<bool,
static_and<is_uniquely_represented<T>::value...>::value &&
static_sum<sizeof(T)...>::value == sizeof(std::tuple<T...>)>
{
};
// is_uniquely_represented<T[N]>
template <class T, std::size_t N>
struct is_uniquely_represented<T[N]>
: public is_uniquely_represented<T>
{
};
// is_uniquely_represented<std::array<T, N>>
template <class T, std::size_t N>
struct is_uniquely_represented<std::array<T, N>>
: public std::integral_constant<bool, is_uniquely_represented<T>::value &&
sizeof(T)*N == sizeof(std::array<T, N>)>
{
};
/** Metafunction returning `true` if the type can be hashed in one call.
For `is_contiguously_hashable<T>::value` to be true, then for every
combination of possible values of `T` held in `x` and `y`,
if `x == y`, then it must be true that `memcmp(&x, &y, sizeof(T))`
return 0; i.e. that `x` and `y` are represented by the same bit pattern.
For example: A two's complement `int` should be contiguously hashable.
Every bit pattern produces a unique value that does not compare equal to
any other bit pattern's value. A IEEE floating point should not be
contiguously hashable because -0. and 0. have different bit patterns,
though they compare equal.
*/
/** @{ */
template <class T, class HashAlgorithm>
struct is_contiguously_hashable
: public std::integral_constant<bool, is_uniquely_represented<T>::value &&
(sizeof(T) == 1 ||
HashAlgorithm::endian == endian::native)>
{};
template <class T, std::size_t N, class HashAlgorithm>
struct is_contiguously_hashable<T[N], HashAlgorithm>
: public std::integral_constant<bool, is_uniquely_represented<T[N]>::value &&
(sizeof(T) == 1 ||
HashAlgorithm::endian == endian::native)>
{};
/** @} */
//------------------------------------------------------------------------------
/** Logically concatenate input data to a `Hasher`.
Hasher requirements:
`X` is the type `Hasher`
`h` is a value of type `x`
`p` is a value convertible to `void const*`
`n` is a value of type `std::size_t`, greater than zero
Expression:
`h.append (p, n);`
Throws:
Never
Effect:
Adds the input data to the hasher state.
Expression:
`static_cast<std::size_t>(j)`
Throws:
Never
Effect:
Returns the reslting hash of all the input data.
*/
/** @{ */
// scalars
template <class Hasher, class T>
inline
std::enable_if_t
<
is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, T const& t) noexcept
{
h(std::addressof(t), sizeof(t));
}
template <class Hasher, class T>
inline
std::enable_if_t
<
!is_contiguously_hashable<T, Hasher>::value &&
(std::is_integral<T>::value || std::is_pointer<T>::value || std::is_enum<T>::value)
>
hash_append(Hasher& h, T t) noexcept
{
detail::reverse_bytes(t);
h(std::addressof(t), sizeof(t));
}
template <class Hasher, class T>
inline
std::enable_if_t
<
std::is_floating_point<T>::value
>
hash_append(Hasher& h, T t) noexcept
{
if (t == 0)
t = 0;
detail::maybe_reverse_bytes(t, h);
h(&t, sizeof(t));
}
template <class Hasher>
inline
void
hash_append(Hasher& h, std::nullptr_t) noexcept
{
void const* p = nullptr;
detail::maybe_reverse_bytes(p, h);
h(&p, sizeof(p));
}
// Forward declarations for ADL purposes
template <class Hasher, class T, std::size_t N>
std::enable_if_t
<
!is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, T (&a)[N]) noexcept;
template <class Hasher, class CharT, class Traits, class Alloc>
std::enable_if_t
<
!is_contiguously_hashable<CharT, Hasher>::value
>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
template <class Hasher, class CharT, class Traits, class Alloc>
std::enable_if_t
<
is_contiguously_hashable<CharT, Hasher>::value
>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
template <class Hasher, class T, class U>
std::enable_if_t
<
!is_contiguously_hashable<std::pair<T, U>, Hasher>::value
>
hash_append (Hasher& h, std::pair<T, U> const& p) noexcept;
template <class Hasher, class T, class Alloc>
std::enable_if_t
<
!is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
template <class Hasher, class T, class Alloc>
std::enable_if_t
<
is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
template <class Hasher, class T, std::size_t N>
std::enable_if_t
<
!is_contiguously_hashable<std::array<T, N>, Hasher>::value
>
hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
template <class Hasher, class ...T>
std::enable_if_t
<
!is_contiguously_hashable<std::tuple<T...>, Hasher>::value
>
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
void
hash_append(Hasher& h, std::unordered_map<Key, T, Hash, Pred, Alloc> const& m);
template <class Hasher, class Key, class Hash, class Pred, class Alloc>
void
hash_append(Hasher& h, std::unordered_set<Key, Hash, Pred, Alloc> const& s);
template <class Hasher, class T0, class T1, class ...T>
void
hash_append (Hasher& h, T0 const& t0, T1 const& t1, T const& ...t) noexcept;
// c-array
template <class Hasher, class T, std::size_t N>
std::enable_if_t
<
!is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, T (&a)[N]) noexcept
{
for (auto const& t : a)
hash_append(h, t);
}
// basic_string
template <class Hasher, class CharT, class Traits, class Alloc>
inline
std::enable_if_t
<
!is_contiguously_hashable<CharT, Hasher>::value
>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
{
for (auto c : s)
hash_append(h, c);
hash_append(h, s.size());
}
template <class Hasher, class CharT, class Traits, class Alloc>
inline
std::enable_if_t
<
is_contiguously_hashable<CharT, Hasher>::value
>
hash_append(Hasher& h, std::basic_string<CharT, Traits, Alloc> const& s) noexcept
{
h(s.data(), s.size()*sizeof(CharT));
hash_append(h, s.size());
}
// pair
template <class Hasher, class T, class U>
inline
std::enable_if_t
<
!is_contiguously_hashable<std::pair<T, U>, Hasher>::value
>
hash_append (Hasher& h, std::pair<T, U> const& p) noexcept
{
hash_append (h, p.first, p.second);
}
// vector
template <class Hasher, class T, class Alloc>
inline
std::enable_if_t
<
!is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
{
for (auto const& t : v)
hash_append(h, t);
hash_append(h, v.size());
}
template <class Hasher, class T, class Alloc>
inline
std::enable_if_t
<
is_contiguously_hashable<T, Hasher>::value
>
hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
{
h(v.data(), v.size()*sizeof(T));
hash_append(h, v.size());
}
// array
template <class Hasher, class T, std::size_t N>
std::enable_if_t
<
!is_contiguously_hashable<std::array<T, N>, Hasher>::value
>
hash_append(Hasher& h, std::array<T, N> const& a) noexcept
{
for (auto const& t : a)
hash_append(h, t);
}
// tuple
namespace detail
{
inline
void
for_each_item(...) noexcept
{
}
template <class Hasher, class T>
inline
int
hash_one(Hasher& h, T const& t) noexcept
{
hash_append(h, t);
return 0;
}
template <class Hasher, class ...T, std::size_t ...I>
inline
void
tuple_hash(Hasher& h, std::tuple<T...> const& t, std::index_sequence<I...>) noexcept
{
for_each_item(hash_one(h, std::get<I>(t))...);
}
} // detail
template <class Hasher, class ...T>
inline
std::enable_if_t
<
!is_contiguously_hashable<std::tuple<T...>, Hasher>::value
>
hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
{
detail::tuple_hash(h, t, std::index_sequence_for<T...>{});
}
// shared_ptr
template <class Hasher, class T>
inline
void
hash_append (Hasher& h, std::shared_ptr<T> const& p) noexcept
{
hash_append(h, p.get());
}
// chrono
template <class Hasher, class Rep, class Period>
inline
void
hash_append (Hasher& h, std::chrono::duration<Rep, Period> const& d) noexcept
{
hash_append(h, d.count());
}
template <class Hasher, class Clock, class Duration>
inline
void
hash_append (Hasher& h, std::chrono::time_point<Clock, Duration> const& tp) noexcept
{
hash_append(h, tp.time_since_epoch());
}
// variadic
template <class Hasher, class T0, class T1, class ...T>
inline
void
hash_append (Hasher& h, T0 const& t0, T1 const& t1, T const& ...t) noexcept
{
hash_append(h, t0);
hash_append(h, t1, t...);
}
// error_code
template <class HashAlgorithm>
inline
void
hash_append(HashAlgorithm& h, std::error_code const& ec)
{
hash_append(h, ec.value(), &ec.category());
}
} // beast
#endif

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#if BEAST_INCLUDE_BEASTCONFIG
#include <BeastConfig.h>
#endif
#include <beast/container/fnv1a.h>
#include <beast/container/siphash.h>
#include <beast/container/xxhasher.h>
#include <beast/rngfill.h>
#include <beast/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <random>
namespace beast {
class hash_speed_test : public beast::unit_test::suite
{
public:
using clock_type =
std::chrono::high_resolution_clock;
template <class Hasher, std::size_t KeySize>
void
test (std::string const& what, std::size_t n)
{
using namespace std;
using namespace std::chrono;
xor_shift_engine g(1);
array<std::uint8_t, KeySize> key;
auto const start = clock_type::now();
while(n--)
{
rngfill (key, g);
Hasher h;
h.append(key.data(), KeySize);
volatile size_t temp =
static_cast<std::size_t>(h);
(void)temp;
}
auto const elapsed = clock_type::now() - start;
log << setw(12) << what << " " <<
duration<double>(elapsed) << "s";
}
void
run()
{
enum
{
N = 100000000
};
#if ! BEAST_NO_XXHASH
test<xxhasher,32> ("xxhash", N);
#endif
test<fnv1a,32> ("fnv1a", N);
test<siphash,32> ("siphash", N);
pass();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
} // beast

View File

@@ -0,0 +1,165 @@
//------------------------------- siphash.h ------------------------------------
//
// This software is in the public domain. The only restriction on its use is
// that no one can remove it from the public domain by claiming ownership of it,
// including the original authors.
//
// There is no warranty of correctness on the software contained herein. Use
// at your own risk.
//
// Derived from:
//
// SipHash reference C implementation
//
// Written in 2012 by Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
// Daniel J. Bernstein <djb@cr.yp.to>
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related and neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see
// <http://creativecommons.org/publicdomain/zero/1.0/>.
//
//------------------------------------------------------------------------------
#include <ripple/beast/hash/siphash.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
// namespace acme is used to demonstrate example code. It is not proposed.
namespace beast {
namespace detail {
using u64 = std::uint64_t;
using u32 = std::uint32_t;
using u8 = std::uint8_t;
inline
u64
rotl(u64 x, u64 b)
{
return (x << b) | (x >> (64 - b));
}
inline
u64
u8to64_le(const u8* p)
{
#if BEAST_LITTLE_ENDIAN
return *static_cast<u64 const*>(static_cast<void const*>(p));
#else
return static_cast<u64>(p[7]) << 56 | static_cast<u64>(p[6]) << 48 |
static_cast<u64>(p[5]) << 40 | static_cast<u64>(p[4]) << 32 |
static_cast<u64>(p[3]) << 24 | static_cast<u64>(p[2]) << 16 |
static_cast<u64>(p[1]) << 8 | static_cast<u64>(p[0]);
#endif
}
inline
void
sipround(u64& v0, u64& v1, u64& v2, u64& v3)
{
v0 += v1;
v1 = rotl(v1, 13);
v1 ^= v0;
v0 = rotl(v0, 32);
v2 += v3;
v3 = rotl(v3, 16);
v3 ^= v2;
v0 += v3;
v3 = rotl(v3, 21);
v3 ^= v0;
v2 += v1;
v1 = rotl(v1, 17);
v1 ^= v2;
v2 = rotl(v2, 32);
}
} // detail
siphash::siphash(std::uint64_t k0, std::uint64_t k1) noexcept
{
v3_ ^= k1;
v2_ ^= k0;
v1_ ^= k1;
v0_ ^= k0;
}
void
siphash::operator() (void const* key, std::size_t inlen) noexcept
{
using namespace detail;
u8 const* in = static_cast<const u8*>(key);
total_length_ += inlen;
if (bufsize_ + inlen < 8)
{
std::copy(in, in+inlen, buf_ + bufsize_);
bufsize_ += inlen;
return;
}
if (bufsize_ > 0)
{
auto t = 8 - bufsize_;
std::copy(in, in+t, buf_ + bufsize_);
u64 m = u8to64_le( buf_ );
v3_ ^= m;
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
v0_ ^= m;
in += t;
inlen -= t;
}
bufsize_ = inlen & 7;
u8 const* const end = in + (inlen - bufsize_);
for ( ; in != end; in += 8 )
{
u64 m = u8to64_le( in );
v3_ ^= m;
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
v0_ ^= m;
}
std::copy(end, end + bufsize_, buf_);
}
siphash::operator std::size_t() noexcept
{
using namespace detail;
std::size_t b = static_cast<u64>(total_length_) << 56;
switch(bufsize_)
{
case 7:
b |= static_cast<u64>(buf_[6]) << 48;
case 6:
b |= static_cast<u64>(buf_[5]) << 40;
case 5:
b |= static_cast<u64>(buf_[4]) << 32;
case 4:
b |= static_cast<u64>(buf_[3]) << 24;
case 3:
b |= static_cast<u64>(buf_[2]) << 16;
case 2:
b |= static_cast<u64>(buf_[1]) << 8;
case 1:
b |= static_cast<u64>(buf_[0]);
case 0:
break;
}
v3_ ^= b;
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
v0_ ^= b;
v2_ ^= 0xff;
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
sipround(v0_, v1_, v2_, v3_);
b = v0_ ^ v1_ ^ v2_ ^ v3_;
return b;
}
} // beast

View File

@@ -0,0 +1,361 @@
// Spooky Hash
// A 128-bit noncryptographic hash, for checksums and table lookup
// By Bob Jenkins. Public domain.
// Oct 31 2010: published framework, disclaimer ShortHash isn't right
// Nov 7 2010: disabled ShortHash
// Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
// April 10 2012: buffer overflow on platforms without unaligned reads
// July 12 2012: was passing out variables in final to in/out in short
// July 30 2012: I reintroduced the buffer overflow
// August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash
#include <memory.h>
#include <ripple/beast/hash/impl/spookyv2.h>
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4127) // conditional expression is constant
#pragma warning (disable: 4244) // conversion from 'size_t' to 'uint8', possible loss of data
#endif
#define ALLOW_UNALIGNED_READS 1
//
// short hash ... it could be used on any message,
// but it's used by Spooky just for short messages.
//
void SpookyHash::Short(
const void *message,
size_t length,
uint64 *hash1,
uint64 *hash2)
{
uint64 buf[2*sc_numVars];
union
{
const uint8 *p8;
uint32 *p32;
uint64 *p64;
size_t i;
} u;
u.p8 = (const uint8 *)message;
if (!ALLOW_UNALIGNED_READS && (u.i & 0x7))
{
memcpy(buf, message, length);
u.p64 = buf;
}
size_t remainder = length%32;
uint64 a=*hash1;
uint64 b=*hash2;
uint64 c=sc_const;
uint64 d=sc_const;
if (length > 15)
{
const uint64 *end = u.p64 + (length/32)*4;
// handle all complete sets of 32 bytes
for (; u.p64 < end; u.p64 += 4)
{
c += u.p64[0];
d += u.p64[1];
ShortMix(a,b,c,d);
a += u.p64[2];
b += u.p64[3];
}
//Handle the case of 16+ remaining bytes.
if (remainder >= 16)
{
c += u.p64[0];
d += u.p64[1];
ShortMix(a,b,c,d);
u.p64 += 2;
remainder -= 16;
}
}
// Handle the last 0..15 bytes, and its length
d += ((uint64)length) << 56;
switch (remainder)
{
case 15:
d += ((uint64)u.p8[14]) << 48;
case 14:
d += ((uint64)u.p8[13]) << 40;
case 13:
d += ((uint64)u.p8[12]) << 32;
case 12:
d += u.p32[2];
c += u.p64[0];
break;
case 11:
d += ((uint64)u.p8[10]) << 16;
case 10:
d += ((uint64)u.p8[9]) << 8;
case 9:
d += (uint64)u.p8[8];
case 8:
c += u.p64[0];
break;
case 7:
c += ((uint64)u.p8[6]) << 48;
case 6:
c += ((uint64)u.p8[5]) << 40;
case 5:
c += ((uint64)u.p8[4]) << 32;
case 4:
c += u.p32[0];
break;
case 3:
c += ((uint64)u.p8[2]) << 16;
case 2:
c += ((uint64)u.p8[1]) << 8;
case 1:
c += (uint64)u.p8[0];
break;
case 0:
c += sc_const;
d += sc_const;
}
ShortEnd(a,b,c,d);
*hash1 = a;
*hash2 = b;
}
// do the whole hash in one call
void SpookyHash::Hash128(
const void *message,
size_t length,
uint64 *hash1,
uint64 *hash2)
{
if (length < sc_bufSize)
{
Short(message, length, hash1, hash2);
return;
}
uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
uint64 buf[sc_numVars];
uint64 *end;
union
{
const uint8 *p8;
uint64 *p64;
size_t i;
} u;
size_t remainder;
h0=h3=h6=h9 = *hash1;
h1=h4=h7=h10 = *hash2;
h2=h5=h8=h11 = sc_const;
u.p8 = (const uint8 *)message;
end = u.p64 + (length/sc_blockSize)*sc_numVars;
// handle all whole sc_blockSize blocks of bytes
if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
{
while (u.p64 < end)
{
Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
u.p64 += sc_numVars;
}
}
else
{
while (u.p64 < end)
{
memcpy(buf, u.p64, sc_blockSize);
Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
u.p64 += sc_numVars;
}
}
// handle the last partial block of sc_blockSize bytes
remainder = (length - ((const uint8 *)end-(const uint8 *)message));
memcpy(buf, end, remainder);
memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder);
((uint8 *)buf)[sc_blockSize-1] =
static_cast<uint8>(remainder);
// do some final mixing
End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
*hash1 = h0;
*hash2 = h1;
}
// init spooky state
void SpookyHash::Init(uint64 seed1, uint64 seed2)
{
m_length = 0;
m_remainder = 0;
m_state[0] = seed1;
m_state[1] = seed2;
}
// add a message fragment to the state
void SpookyHash::Update(const void *message, size_t length)
{
uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
size_t newLength = length + m_remainder;
uint8 remainder;
union
{
const uint8 *p8;
uint64 *p64;
size_t i;
} u;
const uint64 *end;
// Is this message fragment too short? If it is, stuff it away.
if (newLength < sc_bufSize)
{
memcpy(&((uint8 *)m_data)[m_remainder], message, length);
m_length = length + m_length;
m_remainder = (uint8)newLength;
return;
}
// init the variables
if (m_length < sc_bufSize)
{
h0=h3=h6=h9 = m_state[0];
h1=h4=h7=h10 = m_state[1];
h2=h5=h8=h11 = sc_const;
}
else
{
h0 = m_state[0];
h1 = m_state[1];
h2 = m_state[2];
h3 = m_state[3];
h4 = m_state[4];
h5 = m_state[5];
h6 = m_state[6];
h7 = m_state[7];
h8 = m_state[8];
h9 = m_state[9];
h10 = m_state[10];
h11 = m_state[11];
}
m_length = length + m_length;
// if we've got anything stuffed away, use it now
if (m_remainder)
{
uint8 prefix = sc_bufSize-m_remainder;
memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix);
u.p64 = m_data;
Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
u.p8 = ((const uint8 *)message) + prefix;
length -= prefix;
}
else
{
u.p8 = (const uint8 *)message;
}
// handle all whole blocks of sc_blockSize bytes
end = u.p64 + (length/sc_blockSize)*sc_numVars;
remainder = (uint8)(length-((const uint8 *)end-u.p8));
if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
{
while (u.p64 < end)
{
Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
u.p64 += sc_numVars;
}
}
else
{
while (u.p64 < end)
{
memcpy(m_data, u.p8, sc_blockSize);
Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
u.p64 += sc_numVars;
}
}
// stuff away the last few bytes
m_remainder = remainder;
memcpy(m_data, end, remainder);
// stuff away the variables
m_state[0] = h0;
m_state[1] = h1;
m_state[2] = h2;
m_state[3] = h3;
m_state[4] = h4;
m_state[5] = h5;
m_state[6] = h6;
m_state[7] = h7;
m_state[8] = h8;
m_state[9] = h9;
m_state[10] = h10;
m_state[11] = h11;
}
// report the hash for the concatenation of all message fragments so far
void SpookyHash::Final(uint64 *hash1, uint64 *hash2)
{
// init the variables
if (m_length < sc_bufSize)
{
*hash1 = m_state[0];
*hash2 = m_state[1];
Short( m_data, m_length, hash1, hash2);
return;
}
const uint64 *data = (const uint64 *)m_data;
uint8 remainder = m_remainder;
uint64 h0 = m_state[0];
uint64 h1 = m_state[1];
uint64 h2 = m_state[2];
uint64 h3 = m_state[3];
uint64 h4 = m_state[4];
uint64 h5 = m_state[5];
uint64 h6 = m_state[6];
uint64 h7 = m_state[7];
uint64 h8 = m_state[8];
uint64 h9 = m_state[9];
uint64 h10 = m_state[10];
uint64 h11 = m_state[11];
if (remainder >= sc_blockSize)
{
// m_data can contain two blocks; handle any whole first block
Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
data += sc_numVars;
remainder -= sc_blockSize;
}
// mix in the last partial block, and the length mod sc_blockSize
memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder));
((uint8 *)data)[sc_blockSize-1] = remainder;
// do some final mixing
End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
*hash1 = h0;
*hash2 = h1;
}
#ifdef _MSC_VER
#pragma warning (pop)
#endif

View File

@@ -0,0 +1,301 @@
//
// SpookyHash: a 128-bit noncryptographic hash function
// By Bob Jenkins, public domain
// Oct 31 2010: alpha, framework + SpookyHash::Mix appears right
// Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right
// Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas
// Feb 2 2012: production, same bits as beta
// Feb 5 2012: adjusted definitions of uint* to be more portable
// Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough.
// August 5 2012: SpookyV2 (different results)
//
// Up to 3 bytes/cycle for long messages. Reasonably fast for short messages.
// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit.
//
// This was developed for and tested on 64-bit x86-compatible processors.
// It assumes the processor is little-endian. There is a macro
// controlling whether unaligned reads are allowed (by default they are).
// This should be an equally good hash on big-endian machines, but it will
// compute different results on them than on little-endian machines.
//
// Google's CityHash has similar specs to SpookyHash, and CityHash is faster
// on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders
// of magnitude slower. CRCs are two or more times slower, but unlike
// SpookyHash, they have nice math for combining the CRCs of pieces to form
// the CRCs of wholes. There are also cryptographic hashes, but those are even
// slower than MD5.
//
#ifndef BEAST_HASH_SPOOKYV2_H_INCLUDED
#define BEAST_HASH_SPOOKYV2_H_INCLUDED
#include <stddef.h>
#ifdef _MSC_VER
# define INLINE __forceinline
typedef unsigned __int64 uint64;
typedef unsigned __int32 uint32;
typedef unsigned __int16 uint16;
typedef unsigned __int8 uint8;
#else
#include <stdint.h>
# define INLINE inline
typedef uint64_t uint64;
typedef uint32_t uint32;
typedef uint16_t uint16;
typedef uint8_t uint8;
#endif
class SpookyHash
{
public:
//
// SpookyHash: hash a single message in one call, produce 128-bit output
//
static void Hash128(
const void *message, // message to hash
size_t length, // length of message in bytes
uint64 *hash1, // in/out: in seed 1, out hash value 1
uint64 *hash2); // in/out: in seed 2, out hash value 2
//
// Hash64: hash a single message in one call, return 64-bit output
//
static uint64 Hash64(
const void *message, // message to hash
size_t length, // length of message in bytes
uint64 seed) // seed
{
uint64 hash1 = seed;
Hash128(message, length, &hash1, &seed);
return hash1;
}
//
// Hash32: hash a single message in one call, produce 32-bit output
//
static uint32 Hash32(
const void *message, // message to hash
size_t length, // length of message in bytes
uint32 seed) // seed
{
uint64 hash1 = seed, hash2 = seed;
Hash128(message, length, &hash1, &hash2);
return (uint32)hash1;
}
//
// Init: initialize the context of a SpookyHash
//
void Init(
uint64 seed1, // any 64-bit value will do, including 0
uint64 seed2); // different seeds produce independent hashes
//
// Update: add a piece of a message to a SpookyHash state
//
void Update(
const void *message, // message fragment
size_t length); // length of message fragment in bytes
//
// Final: compute the hash for the current SpookyHash state
//
// This does not modify the state; you can keep updating it afterward
//
// The result is the same as if SpookyHash() had been called with
// all the pieces concatenated into one message.
//
void Final(
uint64 *hash1, // out only: first 64 bits of hash value.
uint64 *hash2); // out only: second 64 bits of hash value.
//
// left rotate a 64-bit value by k bytes
//
static INLINE uint64 Rot64(uint64 x, int k)
{
return (x << k) | (x >> (64 - k));
}
//
// This is used if the input is 96 bytes long or longer.
//
// The internal state is fully overwritten every 96 bytes.
// Every input bit appears to cause at least 128 bits of entropy
// before 96 other bytes are combined, when run forward or backward
// For every input bit,
// Two inputs differing in just that input bit
// Where "differ" means xor or subtraction
// And the base value is random
// When run forward or backwards one Mix
// I tried 3 pairs of each; they all differed by at least 212 bits.
//
static INLINE void Mix(
const uint64 *data,
uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3,
uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7,
uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11)
{
s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1;
s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2;
s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3;
s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4;
s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5;
s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6;
s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7;
s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8;
s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9;
s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10;
s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11;
s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0;
}
//
// Mix all 12 inputs together so that h0, h1 are a hash of them all.
//
// For two inputs differing in just the input bits
// Where "differ" means xor or subtraction
// And the base value is random, or a counting value starting at that bit
// The final result will have each bit of h0, h1 flip
// For every input bit,
// with probability 50 +- .3%
// For every pair of input bits,
// with probability 50 +- 3%
//
// This does not rely on the last Mix() call having already mixed some.
// Two iterations was almost good enough for a 64-bit result, but a
// 128-bit result is reported, so End() does three iterations.
//
static INLINE void EndPartial(
uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3,
uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7,
uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11)
{
h11+= h1; h2 ^= h11; h1 = Rot64(h1,44);
h0 += h2; h3 ^= h0; h2 = Rot64(h2,15);
h1 += h3; h4 ^= h1; h3 = Rot64(h3,34);
h2 += h4; h5 ^= h2; h4 = Rot64(h4,21);
h3 += h5; h6 ^= h3; h5 = Rot64(h5,38);
h4 += h6; h7 ^= h4; h6 = Rot64(h6,33);
h5 += h7; h8 ^= h5; h7 = Rot64(h7,10);
h6 += h8; h9 ^= h6; h8 = Rot64(h8,13);
h7 += h9; h10^= h7; h9 = Rot64(h9,38);
h8 += h10; h11^= h8; h10= Rot64(h10,53);
h9 += h11; h0 ^= h9; h11= Rot64(h11,42);
h10+= h0; h1 ^= h10; h0 = Rot64(h0,54);
}
static INLINE void End(
const uint64 *data,
uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3,
uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7,
uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11)
{
h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3];
h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7];
h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11];
EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
}
//
// The goal is for each bit of the input to expand into 128 bits of
// apparent entropy before it is fully overwritten.
// n trials both set and cleared at least m bits of h0 h1 h2 h3
// n: 2 m: 29
// n: 3 m: 46
// n: 4 m: 57
// n: 5 m: 107
// n: 6 m: 146
// n: 7 m: 152
// when run forwards or backwards
// for all 1-bit and 2-bit diffs
// with diffs defined by either xor or subtraction
// with a base of all zeros plus a counter, or plus another bit, or random
//
static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
{
h2 = Rot64(h2,50); h2 += h3; h0 ^= h2;
h3 = Rot64(h3,52); h3 += h0; h1 ^= h3;
h0 = Rot64(h0,30); h0 += h1; h2 ^= h0;
h1 = Rot64(h1,41); h1 += h2; h3 ^= h1;
h2 = Rot64(h2,54); h2 += h3; h0 ^= h2;
h3 = Rot64(h3,48); h3 += h0; h1 ^= h3;
h0 = Rot64(h0,38); h0 += h1; h2 ^= h0;
h1 = Rot64(h1,37); h1 += h2; h3 ^= h1;
h2 = Rot64(h2,62); h2 += h3; h0 ^= h2;
h3 = Rot64(h3,34); h3 += h0; h1 ^= h3;
h0 = Rot64(h0,5); h0 += h1; h2 ^= h0;
h1 = Rot64(h1,36); h1 += h2; h3 ^= h1;
}
//
// Mix all 4 inputs together so that h0, h1 are a hash of them all.
//
// For two inputs differing in just the input bits
// Where "differ" means xor or subtraction
// And the base value is random, or a counting value starting at that bit
// The final result will have each bit of h0, h1 flip
// For every input bit,
// with probability 50 +- .3% (it is probably better than that)
// For every pair of input bits,
// with probability 50 +- .75% (the worst case is approximately that)
//
static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3)
{
h3 ^= h2; h2 = Rot64(h2,15); h3 += h2;
h0 ^= h3; h3 = Rot64(h3,52); h0 += h3;
h1 ^= h0; h0 = Rot64(h0,26); h1 += h0;
h2 ^= h1; h1 = Rot64(h1,51); h2 += h1;
h3 ^= h2; h2 = Rot64(h2,28); h3 += h2;
h0 ^= h3; h3 = Rot64(h3,9); h0 += h3;
h1 ^= h0; h0 = Rot64(h0,47); h1 += h0;
h2 ^= h1; h1 = Rot64(h1,54); h2 += h1;
h3 ^= h2; h2 = Rot64(h2,32); h3 += h2;
h0 ^= h3; h3 = Rot64(h3,25); h0 += h3;
h1 ^= h0; h0 = Rot64(h0,63); h1 += h0;
}
private:
//
// Short is used for messages under 192 bytes in length
// Short has a low startup cost, the normal mode is good for long
// keys, the cost crossover is at about 192 bytes. The two modes were
// held to the same quality bar.
//
static void Short(
const void *message, // message (array of bytes, not necessarily aligned)
size_t length, // length of message (in bytes)
uint64 *hash1, // in/out: in the seed, out the hash value
uint64 *hash2); // in/out: in the seed, out the hash value
// number of uint64's in internal state
static const size_t sc_numVars = 12;
// size of the internal state
static const size_t sc_blockSize = sc_numVars*8;
// size of buffer of unhashed data, in bytes
static const size_t sc_bufSize = 2*sc_blockSize;
//
// sc_const: a constant which:
// * is not zero
// * is odd
// * is a not-very-regular mix of 1's and 0's
// * does not need any other special mathematical properties
//
static const uint64 sc_const = 0xdeadbeefdeadbeefUL;
uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages
uint64 m_state[sc_numVars]; // internal state of the hash
size_t m_length; // total length of the input so far
uint8 m_remainder; // length of unhashed data stashed in m_data
};
#endif // BEAST_SPOOKYV2_H_INCLUDED

View File

@@ -0,0 +1,934 @@
/*
xxHash - Fast Hash algorithm
Copyright (C) 2012-2014, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : http://code.google.com/p/xxhash/
- public discussion board : https://groups.google.com/forum/#!forum/lz4c
*/
#include <ripple/beast/hash/impl/xxhash.h>
//**************************************
// Tuning parameters
//**************************************
// Unaligned memory access is automatically enabled for "common" CPU, such as x86.
// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# define XXH_USE_UNALIGNED_ACCESS 1
#endif
// XXH_ACCEPT_NULL_INPUT_POINTER :
// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
// This option has a very small performance cost (only measurable on small inputs).
// By default, this option is disabled. To enable it, uncomment below define :
// #define XXH_ACCEPT_NULL_INPUT_POINTER 1
// XXH_FORCE_NATIVE_FORMAT :
// By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
// Results are therefore identical for little-endian and big-endian CPU.
// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
// Should endian-independance be of no importance for your application, you may set the #define below to 1.
// It will improve speed for Big-endian CPU.
// This option has no impact on Little_Endian CPU.
#define XXH_FORCE_NATIVE_FORMAT 0
//**************************************
// Compiler Specific Options
//**************************************
// Disable some Visual warning messages
#ifdef _MSC_VER // Visual Studio
# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant
#endif
#ifdef _MSC_VER // Visual Studio
# define FORCE_INLINE static __forceinline
#else
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
#endif
//**************************************
// Includes & Memory related functions
//**************************************
//#include "xxhash.h"
// Modify the local functions below should you wish to use some other memory routines
// for malloc(), free()
#include <stdlib.h>
static void* XXH_malloc(size_t s) { return malloc(s); }
static void XXH_free (void* p) { free(p); }
// for memcpy()
#include <string.h>
static void* XXH_memcpy(void* dest, const void* src, size_t size)
{
return memcpy(dest,src,size);
}
//**************************************
// Basic Types
//**************************************
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99
# include <stdint.h>
typedef uint8_t BYTE;
typedef uint16_t U16;
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
#else
typedef unsigned char BYTE;
typedef unsigned short U16;
typedef unsigned int U32;
typedef signed int S32;
typedef unsigned long long U64;
#endif
#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
# define _PACKED __attribute__ ((packed))
#else
# define _PACKED
#endif
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# ifdef __IBMC__
# pragma pack(1)
# else
# pragma pack(push, 1)
# endif
#endif
namespace beast {
namespace detail {
typedef struct _U32_S
{
U32 v;
} _PACKED U32_S;
typedef struct _U64_S
{
U64 v;
} _PACKED U64_S;
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# pragma pack(pop)
#endif
#define A32(x) (((U32_S *)(x))->v)
#define A64(x) (((U64_S *)(x))->v)
//***************************************
// Compiler-specific Functions and Macros
//***************************************
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
// Note : although _rotl exists for minGW (GCC under windows), performance seems poor
#if defined(_MSC_VER)
# define XXH_rotl32(x,r) _rotl(x,r)
# define XXH_rotl64(x,r) _rotl64(x,r)
#else
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
#endif
#if defined(_MSC_VER) // Visual Studio
# define XXH_swap32 _byteswap_ulong
# define XXH_swap64 _byteswap_uint64
#elif GCC_VERSION >= 403
# define XXH_swap32 __builtin_bswap32
# define XXH_swap64 __builtin_bswap64
#else
static inline U32 XXH_swap32 (U32 x)
{
return ((x << 24) & 0xff000000 ) |
((x << 8) & 0x00ff0000 ) |
((x >> 8) & 0x0000ff00 ) |
((x >> 24) & 0x000000ff );
}
static inline U64 XXH_swap64 (U64 x)
{
return ((x << 56) & 0xff00000000000000ULL) |
((x << 40) & 0x00ff000000000000ULL) |
((x << 24) & 0x0000ff0000000000ULL) |
((x << 8) & 0x000000ff00000000ULL) |
((x >> 8) & 0x00000000ff000000ULL) |
((x >> 24) & 0x0000000000ff0000ULL) |
((x >> 40) & 0x000000000000ff00ULL) |
((x >> 56) & 0x00000000000000ffULL);
}
#endif
//**************************************
// Constants
//**************************************
#define PRIME32_1 2654435761U
#define PRIME32_2 2246822519U
#define PRIME32_3 3266489917U
#define PRIME32_4 668265263U
#define PRIME32_5 374761393U
#define PRIME64_1 11400714785074694791ULL
#define PRIME64_2 14029467366897019727ULL
#define PRIME64_3 1609587929392839161ULL
#define PRIME64_4 9650029242287828579ULL
#define PRIME64_5 2870177450012600261ULL
//**************************************
// Architecture Macros
//**************************************
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
static const int one = 1;
# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one))
#endif
//**************************************
// Macros
//**************************************
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations
//****************************
// Memory reads
//****************************
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
else
return endian==XXH_littleEndian ? *(U32*)ptr : XXH_swap32(*(U32*)ptr);
}
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
{
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
}
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
{
if (align==XXH_unaligned)
return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr));
else
return endian==XXH_littleEndian ? *(U64*)ptr : XXH_swap64(*(U64*)ptr);
}
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
{
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
}
//****************************
// Simple Hash Functions
//****************************
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U32 h32;
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (p==NULL)
{
len=0;
bEnd=p=(const BYTE*)(size_t)16;
}
#endif
if (len>=16)
{
const BYTE* const limit = bEnd - 16;
U32 v1 = seed + PRIME32_1 + PRIME32_2;
U32 v2 = seed + PRIME32_2;
U32 v3 = seed + 0;
U32 v4 = seed - PRIME32_1;
do
{
v1 += XXH_get32bits(p) * PRIME32_2;
v1 = XXH_rotl32(v1, 13);
v1 *= PRIME32_1;
p+=4;
v2 += XXH_get32bits(p) * PRIME32_2;
v2 = XXH_rotl32(v2, 13);
v2 *= PRIME32_1;
p+=4;
v3 += XXH_get32bits(p) * PRIME32_2;
v3 = XXH_rotl32(v3, 13);
v3 *= PRIME32_1;
p+=4;
v4 += XXH_get32bits(p) * PRIME32_2;
v4 = XXH_rotl32(v4, 13);
v4 *= PRIME32_1;
p+=4;
}
while (p<=limit);
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
}
else
{
h32 = seed + PRIME32_5;
}
h32 += (U32) len;
while (p+4<=bEnd)
{
h32 += XXH_get32bits(p) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
p+=4;
}
while (p<bEnd)
{
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
unsigned int XXH32 (const void* input, size_t len, unsigned seed)
{
#if 0
// Simple version, good for code maintenance, but unfortunately slow for small inputs
XXH32_state_t state;
XXH32_reset(&state, seed);
XXH32_update(&state, input, len);
return XXH32_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
# if !defined(XXH_USE_UNALIGNED_ACCESS)
if ((((size_t)input) & 3) == 0) // Input is aligned, let's leverage the speed advantage
{
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
}
# endif
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
{
const BYTE* p = (const BYTE*)input;
const BYTE* bEnd = p + len;
U64 h64;
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (p==NULL)
{
len=0;
bEnd=p=(const BYTE*)(size_t)32;
}
#endif
if (len>=32)
{
const BYTE* const limit = bEnd - 32;
U64 v1 = seed + PRIME64_1 + PRIME64_2;
U64 v2 = seed + PRIME64_2;
U64 v3 = seed + 0;
U64 v4 = seed - PRIME64_1;
do
{
v1 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
v2 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
v3 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
v4 += XXH_get64bits(p) * PRIME64_2;
p+=8;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
}
while (p<=limit);
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
v1 *= PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64 * PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64 * PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64 * PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64 * PRIME64_1 + PRIME64_4;
}
else
{
h64 = seed + PRIME64_5;
}
h64 += (U64) len;
while (p+8<=bEnd)
{
U64 k1 = XXH_get64bits(p);
k1 *= PRIME64_2;
k1 = XXH_rotl64(k1,31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd)
{
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd)
{
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
{
#if 0
// Simple version, good for code maintenance, but unfortunately slow for small inputs
XXH64_state_t state;
XXH64_reset(&state, seed);
XXH64_update(&state, input, len);
return XXH64_digest(&state);
#else
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
# if !defined(XXH_USE_UNALIGNED_ACCESS)
if ((((size_t)input) & 7)==0) // Input is aligned, let's leverage the speed advantage
{
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
}
# endif
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
else
return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
#endif
}
/****************************************************
* Advanced Hash Functions
****************************************************/
/*** Allocation ***/
typedef struct
{
U64 total_len;
U32 seed;
U32 v1;
U32 v2;
U32 v3;
U32 v4;
U32 mem32[4]; /* defined as U32 for alignment */
U32 memsize;
} XXH_istate32_t;
typedef struct
{
U64 total_len;
U64 seed;
U64 v1;
U64 v2;
U64 v3;
U64 v4;
U64 mem64[4]; /* defined as U64 for alignment */
U32 memsize;
} XXH_istate64_t;
XXH32_state_t* XXH32_createState(void)
{
static_assert(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t), ""); // A compilation error here means XXH32_state_t is not large enough
return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
}
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
};
XXH64_state_t* XXH64_createState(void)
{
static_assert(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t), ""); // A compilation error here means XXH64_state_t is not large enough
return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
}
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
{
XXH_free(statePtr);
return XXH_OK;
};
/*** Hash feed ***/
XXH_errorcode XXH32_reset(XXH32_state_t* state_in, U32 seed)
{
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
state->seed = seed;
state->v1 = seed + PRIME32_1 + PRIME32_2;
state->v2 = seed + PRIME32_2;
state->v3 = seed + 0;
state->v4 = seed - PRIME32_1;
state->total_len = 0;
state->memsize = 0;
return XXH_OK;
}
XXH_errorcode XXH64_reset(XXH64_state_t* state_in, unsigned long long seed)
{
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
state->seed = seed;
state->v1 = seed + PRIME64_1 + PRIME64_2;
state->v2 = seed + PRIME64_2;
state->v3 = seed + 0;
state->v4 = seed - PRIME64_1;
state->total_len = 0;
state->memsize = 0;
return XXH_OK;
}
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
{
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (input==NULL) return XXH_ERROR;
#endif
state->total_len += len;
if (state->memsize + len < 16) // fill in tmp buffer
{
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
state->memsize += (U32)len;
return XXH_OK;
}
if (state->memsize) // some data left from previous update
{
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
{
const U32* p32 = state->mem32;
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v1 = XXH_rotl32(state->v1, 13);
state->v1 *= PRIME32_1;
p32++;
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v2 = XXH_rotl32(state->v2, 13);
state->v2 *= PRIME32_1;
p32++;
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v3 = XXH_rotl32(state->v3, 13);
state->v3 *= PRIME32_1;
p32++;
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
state->v4 = XXH_rotl32(state->v4, 13);
state->v4 *= PRIME32_1;
p32++;
}
p += 16-state->memsize;
state->memsize = 0;
}
if (p <= bEnd-16)
{
const BYTE* const limit = bEnd - 16;
U32 v1 = state->v1;
U32 v2 = state->v2;
U32 v3 = state->v3;
U32 v4 = state->v4;
do
{
v1 += XXH_readLE32(p, endian) * PRIME32_2;
v1 = XXH_rotl32(v1, 13);
v1 *= PRIME32_1;
p+=4;
v2 += XXH_readLE32(p, endian) * PRIME32_2;
v2 = XXH_rotl32(v2, 13);
v2 *= PRIME32_1;
p+=4;
v3 += XXH_readLE32(p, endian) * PRIME32_2;
v3 = XXH_rotl32(v3, 13);
v3 *= PRIME32_1;
p+=4;
v4 += XXH_readLE32(p, endian) * PRIME32_2;
v4 = XXH_rotl32(v4, 13);
v4 *= PRIME32_1;
p+=4;
}
while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd)
{
XXH_memcpy(state->mem32, p, bEnd-p);
state->memsize = (int)(bEnd-p);
}
return XXH_OK;
}
XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess endian)
{
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
const BYTE * p = (const BYTE*)state->mem32;
BYTE* bEnd = (BYTE*)(state->mem32) + state->memsize;
U32 h32;
if (state->total_len >= 16)
{
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
}
else
{
h32 = state->seed + PRIME32_5;
}
h32 += (U32) state->total_len;
while (p+4<=bEnd)
{
h32 += XXH_readLE32(p, endian) * PRIME32_3;
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
p+=4;
}
while (p<bEnd)
{
h32 += (*p) * PRIME32_5;
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
p++;
}
h32 ^= h32 >> 15;
h32 *= PRIME32_2;
h32 ^= h32 >> 13;
h32 *= PRIME32_3;
h32 ^= h32 >> 16;
return h32;
}
U32 XXH32_digest (const XXH32_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH32_digest_endian(state_in, XXH_littleEndian);
else
return XXH32_digest_endian(state_in, XXH_bigEndian);
}
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
{
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
const BYTE* p = (const BYTE*)input;
const BYTE* const bEnd = p + len;
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
if (input==NULL) return XXH_ERROR;
#endif
state->total_len += len;
if (state->memsize + len < 32) // fill in tmp buffer
{
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
state->memsize += (U32)len;
return XXH_OK;
}
if (state->memsize) // some data left from previous update
{
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
{
const U64* p64 = state->mem64;
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v1 = XXH_rotl64(state->v1, 31);
state->v1 *= PRIME64_1;
p64++;
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v2 = XXH_rotl64(state->v2, 31);
state->v2 *= PRIME64_1;
p64++;
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v3 = XXH_rotl64(state->v3, 31);
state->v3 *= PRIME64_1;
p64++;
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
state->v4 = XXH_rotl64(state->v4, 31);
state->v4 *= PRIME64_1;
p64++;
}
p += 32-state->memsize;
state->memsize = 0;
}
if (p+32 <= bEnd)
{
const BYTE* const limit = bEnd - 32;
U64 v1 = state->v1;
U64 v2 = state->v2;
U64 v3 = state->v3;
U64 v4 = state->v4;
do
{
v1 += XXH_readLE64(p, endian) * PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
p+=8;
v2 += XXH_readLE64(p, endian) * PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
p+=8;
v3 += XXH_readLE64(p, endian) * PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
p+=8;
v4 += XXH_readLE64(p, endian) * PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
p+=8;
}
while (p<=limit);
state->v1 = v1;
state->v2 = v2;
state->v3 = v3;
state->v4 = v4;
}
if (p < bEnd)
{
XXH_memcpy(state->mem64, p, bEnd-p);
state->memsize = (int)(bEnd-p);
}
return XXH_OK;
}
XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
else
return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
}
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess endian)
{
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
const BYTE * p = (const BYTE*)state->mem64;
BYTE* bEnd = (BYTE*)state->mem64 + state->memsize;
U64 h64;
if (state->total_len >= 32)
{
U64 v1 = state->v1;
U64 v2 = state->v2;
U64 v3 = state->v3;
U64 v4 = state->v4;
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
v1 *= PRIME64_2;
v1 = XXH_rotl64(v1, 31);
v1 *= PRIME64_1;
h64 ^= v1;
h64 = h64*PRIME64_1 + PRIME64_4;
v2 *= PRIME64_2;
v2 = XXH_rotl64(v2, 31);
v2 *= PRIME64_1;
h64 ^= v2;
h64 = h64*PRIME64_1 + PRIME64_4;
v3 *= PRIME64_2;
v3 = XXH_rotl64(v3, 31);
v3 *= PRIME64_1;
h64 ^= v3;
h64 = h64*PRIME64_1 + PRIME64_4;
v4 *= PRIME64_2;
v4 = XXH_rotl64(v4, 31);
v4 *= PRIME64_1;
h64 ^= v4;
h64 = h64*PRIME64_1 + PRIME64_4;
}
else
{
h64 = state->seed + PRIME64_5;
}
h64 += (U64) state->total_len;
while (p+8<=bEnd)
{
U64 k1 = XXH_readLE64(p, endian);
k1 *= PRIME64_2;
k1 = XXH_rotl64(k1,31);
k1 *= PRIME64_1;
h64 ^= k1;
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
p+=8;
}
if (p+4<=bEnd)
{
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
p+=4;
}
while (p<bEnd)
{
h64 ^= (*p) * PRIME64_5;
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
p++;
}
h64 ^= h64 >> 33;
h64 *= PRIME64_2;
h64 ^= h64 >> 29;
h64 *= PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
unsigned long long XXH64_digest (const XXH64_state_t* state_in)
{
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
return XXH64_digest_endian(state_in, XXH_littleEndian);
else
return XXH64_digest_endian(state_in, XXH_bigEndian);
}
} // detail
} // beast

View File

@@ -0,0 +1,154 @@
/*
xxHash - Extremely Fast Hash algorithm
Header File
Copyright (C) 2012-2014, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : http://code.google.com/p/xxhash/
*/
/* Notice extracted from xxHash homepage :
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
It also successfully passes all tests from the SMHasher suite.
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
Name Speed Q.Score Author
xxHash 5.4 GB/s 10
CrapWow 3.2 GB/s 2 Andrew
MumurHash 3a 2.7 GB/s 10 Austin Appleby
SpookyHash 2.0 GB/s 10 Bob Jenkins
SBox 1.4 GB/s 9 Bret Mulvey
Lookup3 1.2 GB/s 9 Bob Jenkins
SuperFastHash 1.2 GB/s 1 Paul Hsieh
CityHash64 1.05 GB/s 10 Pike & Alakuijala
FNV 0.55 GB/s 5 Fowler, Noll, Vo
CRC32 0.43 GB/s 9
MD5-32 0.33 GB/s 10 Ronald L. Rivest
SHA1-32 0.28 GB/s 10
Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
*/
#ifndef BEAST_HASH_XXHASH_H_INCLUDED
#define BEAST_HASH_XXHASH_H_INCLUDED
/*****************************
Includes
*****************************/
#include <stddef.h> /* size_t */
namespace beast {
namespace detail {
/*****************************
Type
*****************************/
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
/*****************************
Simple Hash Functions
*****************************/
unsigned int XXH32 (const void* input, size_t length, unsigned seed);
unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
/*
XXH32() :
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
The memory between input & input+length must be valid (allocated and read-accessible).
"seed" can be used to alter the result predictably.
This function successfully passes all SMHasher tests.
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
XXH64() :
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
*/
/*****************************
Advanced Hash Functions
*****************************/
typedef struct { long long ll[ 6]; } XXH32_state_t;
typedef struct { long long ll[11]; } XXH64_state_t;
/*
These structures allow static allocation of XXH states.
States must then be initialized using XXHnn_reset() before first use.
If you prefer dynamic allocation, please refer to functions below.
*/
XXH32_state_t* XXH32_createState(void);
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
XXH64_state_t* XXH64_createState(void);
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
/*
These functions create and release memory for XXH state.
States must then be initialized using XXHnn_reset() before first use.
*/
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
unsigned int XXH32_digest (const XXH32_state_t* statePtr);
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
unsigned long long XXH64_digest (const XXH64_state_t* statePtr);
/*
These functions calculate the xxHash of an input provided in multiple smaller packets,
as opposed to an input provided as a single block.
XXH state space must first be allocated, using either static or dynamic method provided above.
Start a new hash by initializing state with a seed, using XXHnn_reset().
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
Obviously, input must be valid, meaning allocated and read accessible.
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
Finally, you can produce a hash anytime, by using XXHnn_digest().
This function returns the final nn-bits hash.
You can nonetheless continue feeding the hash state with more input,
and therefore get some new hashes, by calling again XXHnn_digest().
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
*/
} // detail
} // beast
#endif

View File

@@ -0,0 +1,140 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@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_HASH_META_H_INCLUDED
#define BEAST_HASH_META_H_INCLUDED
#include <type_traits>
namespace beast {
template <bool ...> struct static_and;
template <bool b0, bool ... bN>
struct static_and <b0, bN...>
: public std::integral_constant <
bool, b0 && static_and<bN...>::value>
{
};
template <>
struct static_and<>
: public std::true_type
{
};
static_assert( static_and<true, true, true>::value, "");
static_assert(!static_and<true, false, true>::value, "");
template <std::size_t ...>
struct static_sum;
template <std::size_t s0, std::size_t ...sN>
struct static_sum <s0, sN...>
: public std::integral_constant <
std::size_t, s0 + static_sum<sN...>::value>
{
};
template <>
struct static_sum<>
: public std::integral_constant<std::size_t, 0>
{
};
static_assert(static_sum<5, 2, 17, 0>::value == 24, "");
template <class T, class U>
struct enable_if_lvalue
: public std::enable_if
<
std::is_same<std::decay_t<T>, U>::value &&
std::is_lvalue_reference<T>::value
>
{
};
/** Ensure const reference function parameters are valid lvalues.
Some functions, especially class constructors, accept const references and
store them for later use. If any of those parameters are rvalue objects,
the object will be freed as soon as the function returns. This could
potentially lead to a variety of "use after free" errors.
If the function is rewritten as a template using this type and the
parameters references as rvalue references (eg. TX&&), a compiler
error will be generated if an rvalue is provided in the caller.
@code
// Example:
struct X
{
};
struct Y
{
};
struct Unsafe
{
Unsafe (X const& x, Y const& y)
: x_ (x)
, y_ (y)
{
}
X const& x_;
Y const& y_;
};
struct Safe
{
template <class TX, class TY,
class = beast::enable_if_lvalue_t<TX, X>,
class = beast::enable_if_lvalue_t < TY, Y >>
Safe (TX&& x, TY&& y)
: x_ (x)
, y_ (y)
{
}
X const& x_;
Y const& y_;
};
struct demo
{
void
createObjects ()
{
X x {};
Y const y {};
Unsafe u1 (x, y); // ok
Unsafe u2 (X (), y); // compiles, but u2.x_ becomes invalid at the end of the line.
Safe s1 (x, y); // ok
// Safe s2 (X (), y); // compile-time error
}
};
@endcode
*/
template <class T, class U>
using enable_if_lvalue_t = typename enable_if_lvalue<T, U>::type;
} // beast
#endif // BEAST_UTILITY_META_H_INCLUDED

View File

@@ -0,0 +1,60 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_SIPHASH_H_INCLUDED
#define BEAST_HASH_SIPHASH_H_INCLUDED
#include <cstddef>
#include <cstdint>
namespace beast {
// See https://131002.net/siphash/
class siphash
{
private:
std::uint64_t v0_ = 0x736f6d6570736575ULL;
std::uint64_t v1_ = 0x646f72616e646f6dULL;
std::uint64_t v2_ = 0x6c7967656e657261ULL;
std::uint64_t v3_ = 0x7465646279746573ULL;
unsigned char buf_[8];
unsigned bufsize_ = 0;
unsigned total_length_ = 0;
public:
using result_type = std::size_t;
static beast::endian const endian = beast::endian::native;
siphash() = default;
explicit
siphash (std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
void
operator() (void const* key, std::size_t len) noexcept;
explicit
operator std::size_t() noexcept;
};
} // beast
#endif

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_SPOOKY_H_INCLUDED
#define BEAST_HASH_SPOOKY_H_INCLUDED
#include <ripple/beast/hash/endian.h>
#include <ripple/beast/hash/impl/spookyv2.h>
namespace beast {
// See http://burtleburtle.net/bob/hash/spooky.html
class spooky
{
private:
SpookyHash state_;
public:
using result_type = std::size_t;
static beast::endian const endian = beast::endian::native;
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
{
state_.Init (seed1, seed2);
}
void
operator() (void const* key, std::size_t len) noexcept
{
state_.Update (key, len);
}
explicit
operator std::size_t() noexcept
{
std::uint64_t h1, h2;
state_.Final (&h1, &h2);
return static_cast <std::size_t> (h1);
}
};
} // beast
#endif

View File

@@ -0,0 +1,490 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#if BEAST_INCLUDE_BEASTCONFIG
#include <BeastConfig.h>
#endif
#include <ripple/beast/hash/endian.h>
#include <ripple/beast/hash/tests/hash_metrics.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/type_name.h>
#include <array>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <random>
namespace beast {
template <class Block, class Derived>
class block_stream
{
private:
Block m_block;
std::size_t m_size;
std::size_t
needed() const noexcept
{
return sizeof(Block) - m_size;
}
void*
tail() noexcept
{
return ((char *)&m_block) + m_size;
}
protected:
void
finish()
{
if (m_size > 0)
{
// zero-pad
memset (tail(), 0, needed());
static_cast <Derived*> (this)->process_block (m_block);
}
}
public:
block_stream ()
: m_size(0)
{
}
void
operator() (void const* data, std::size_t bytes) noexcept
{
// handle leftovers
if (m_size > 0)
{
std::size_t const n (std::min (needed(), bytes));
std::memcpy (tail(), data, n);
data = ((char const*)data) + n;
bytes -= n;
m_size += n;
if (m_size < sizeof(Block))
return;
static_cast <Derived*> (this)->process_block (m_block);
}
// loop over complete blocks
while (bytes >= sizeof(Block))
{
m_block = *((Block const*)data);
static_cast <Derived*> (this)->process_block (m_block);
data = ((char const*)data) + sizeof(m_block);
bytes -= sizeof(m_block);
}
// save leftovers
if (bytes > 0)
{
memcpy (tail(), data, bytes);
m_size += bytes;
}
}
};
//------------------------------------------------------------------------------
namespace hash_append_tests {
template <std::size_t> class fnv1a_imp;
template <>
class fnv1a_imp<64>
{
private:
std::uint64_t state_ = 14695981039346656037u;
public:
static beast::endian const endian = beast::endian::native;
void
operator() (void const* key, std::size_t len) noexcept
{
unsigned char const* p = static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
state_ = (state_ ^ *p) * 1099511628211u;
}
explicit
operator std::size_t() noexcept
{
return state_;
}
};
template <>
class fnv1a_imp<32>
{
private:
std::uint32_t state_ = 2166136261;
public:
static beast::endian const endian = beast::endian::native;
void
operator() (void const* key, std::size_t len) noexcept
{
unsigned char const* p = static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
state_ = (state_ ^ *p) * 16777619;
}
explicit
operator std::size_t() noexcept
{
return state_;
}
};
class fnv1a
: public fnv1a_imp<CHAR_BIT*sizeof(std::size_t)>
{
public:
};
class jenkins1
{
private:
std::size_t state_ = 0;
public:
static beast::endian const endian = beast::endian::native;
void
operator() (void const* key, std::size_t len) noexcept
{
unsigned char const* p = static_cast <unsigned char const*>(key);
unsigned char const* const e = p + len;
for (; p < e; ++p)
{
state_ += *p;
state_ += state_ << 10;
state_ ^= state_ >> 6;
}
}
explicit
operator std::size_t() noexcept
{
state_ += state_ << 3;
state_ ^= state_ >> 11;
state_ += state_ << 15;
return state_;
}
};
class spooky
{
private:
SpookyHash state_;
public:
static beast::endian const endian = beast::endian::native;
spooky(std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
{
state_.Init(seed1, seed2);
}
void
operator()(void const* key, std::size_t len) noexcept
{
state_.Update(key, len);
}
explicit
operator std::size_t() noexcept
{
std::uint64_t h1, h2;
state_.Final(&h1, &h2);
return h1;
}
};
template <
class PRNG = std::conditional_t <
sizeof(std::size_t)==sizeof(std::uint64_t),
std::mt19937_64,
std::mt19937
>
>
class prng_hasher
: public block_stream <std::size_t, prng_hasher <PRNG>>
{
private:
std::size_t m_seed;
PRNG m_prng;
using base = block_stream <std::size_t, prng_hasher <PRNG>>;
friend base;
// compress
void
process_block (std::size_t block)
{
m_prng.seed (m_seed + block);
m_seed = m_prng();
}
public:
prng_hasher (std::size_t seed = 0)
: m_seed (seed)
{
}
void
operator() (void const* data, std::size_t bytes) noexcept
{
base::operator() (data, bytes);
}
explicit
operator std::size_t() noexcept
{
base::finish();
return m_seed;
}
};
class SlowKey
{
private:
std::tuple <short, unsigned char, unsigned char> date_;
std::vector <std::pair <int, int>> data_;
public:
SlowKey()
{
static beast::xor_shift_engine eng;
std::uniform_int_distribution<short> yeardata(1900, 2014);
std::uniform_int_distribution<unsigned> monthdata(1, 12);
std::uniform_int_distribution<unsigned> daydata(1, 28);
std::uniform_int_distribution<std::size_t> veclen(0, 100);
std::uniform_int_distribution<int> int1data(1, 10);
std::uniform_int_distribution<int> int2data(-3, 5000);
std::get<0>(date_) = yeardata(eng);
std::get<1>(date_) = (unsigned char)monthdata(eng);
std::get<2>(date_) = (unsigned char)daydata(eng);
data_.resize(veclen(eng));
for (auto& p : data_)
{
p.first = int1data(eng);
p.second = int2data(eng);
}
}
// Hook into the system like this
template <class Hasher>
friend
void
hash_append (Hasher& h, SlowKey const& x) noexcept
{
using beast::hash_append;
hash_append (h, x.date_, x.data_);
}
friend
bool operator< (SlowKey const& x, SlowKey const& y) noexcept
{
return std::tie(x.date_, x.data_) < std::tie(y.date_, y.data_);
}
// Hook into the std::system like this
friend struct std::hash<SlowKey>;
friend struct X_fnv1a;
};
struct FastKey
{
private:
std::array <std::size_t, 4> m_values;
public:
FastKey()
{
static beast::xor_shift_engine eng;
for (auto& v : m_values)
v = eng();
}
friend
bool
operator< (FastKey const& x, FastKey const& y) noexcept
{
return x.m_values < y.m_values;
}
};
} // hash_append_tests
//------------------------------------------------------------------------------
template <class HashAlgorithm>
struct is_contiguously_hashable <hash_append_tests::FastKey, HashAlgorithm>
: std::integral_constant<bool, is_contiguously_hashable<std::array <std::size_t, 4>,
HashAlgorithm>::value>
{
};
//------------------------------------------------------------------------------
class hash_append_test : public unit_test::suite
{
public:
using SlowKey = hash_append_tests::SlowKey;
using FastKey = hash_append_tests::FastKey;
struct results_t
{
results_t()
: collision_factor (0)
, distribution_factor (0)
, elapsed (0)
{
}
float collision_factor;
float distribution_factor;
float windowed_score;
std::chrono::milliseconds elapsed;
};
// Generate a set of keys
template <class Key>
std::set <Key>
make_keys (std::size_t count)
{
std::set <Key> keys;
while (count--)
keys.emplace();
return keys;
}
// Generate a set of hashes from a container
template <class Hasher, class Keys>
std::vector <std::size_t>
make_hashes (Keys const& keys)
{
std::vector <std::size_t> hashes;
hashes.reserve (keys.size());
for (auto const& key : keys)
{
Hasher h;
hash_append (h, key);
hashes.push_back (static_cast <std::size_t> (h));
}
return hashes;
}
template <class Hasher, class Hashes>
void
measure_hashes (results_t& results, Hashes const& hashes)
{
results.collision_factor =
hash_metrics::collision_factor (
hashes.begin(), hashes.end());
results.distribution_factor =
hash_metrics::distribution_factor (
hashes.begin(), hashes.end());
results.windowed_score =
hash_metrics::windowed_score (
hashes.begin(), hashes.end());
}
template <class Hasher, class Keys>
void
measure_keys (results_t& results, Keys const& keys)
{
auto const start (
std::chrono::high_resolution_clock::now());
auto const hashes (make_hashes <Hasher> (keys));
results.elapsed = std::chrono::duration_cast <std::chrono::milliseconds> (
std::chrono::high_resolution_clock::now() - start);
measure_hashes <Hasher> (results, hashes);
}
template <class Hasher, class Key>
void
test_hasher (std::string const& name, std::size_t n)
{
results_t results;
auto const keys (make_keys <Key> (n));
measure_keys <Hasher> (results, keys);
report (name, results);
}
void
report (std::string const& name, results_t const& results)
{
log <<
std::left <<
std::setw (39) << name << " | " <<
std::right <<
std::setw (13) << std::setprecision (5) <<
results.collision_factor << " | " <<
std::setw (13) << std::setprecision (5) <<
results.distribution_factor << " | " <<
std::setw (13) << std::setprecision (5) <<
results.windowed_score << " | " <<
std::left <<
results.elapsed.count();
pass ();
}
void
run()
{
log <<
"name | collision | distribution | windowed | time (milliseconds)" << std::endl <<
"----------------------------------------+---------------+---------------+---------------+--------------------";
//test_hasher <hash_append_tests::prng_hasher<>, SlowKey> ("prng_hasher <SlowKey>", 10000);
//test_hasher <hash_append_tests::prng_hasher<>, FastKey> ("prng_hasher <FastKey>", 100000);
test_hasher <hash_append_tests::jenkins1, SlowKey> ("jenkins1 <SlowKey>", 1000000);
test_hasher <hash_append_tests::spooky, SlowKey> ("spooky <SlowKey>", 1000000);
test_hasher <hash_append_tests::fnv1a, SlowKey> ("fnv1a <SlowKey>", 1000000);
test_hasher <hash_append_tests::jenkins1, FastKey> ("jenkins1 <FastKey>", 1000000);
test_hasher <hash_append_tests::spooky, FastKey> ("spooky <FastKey>", 1000000);
test_hasher <hash_append_tests::fnv1a, FastKey> ("fnv1a <FastKey>", 1000000);
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(hash_append,container,beast);
}

View File

@@ -0,0 +1,200 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_HASH_METRICS_H_INCLUDED
#define BEAST_HASH_HASH_METRICS_H_INCLUDED
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstddef>
#include <cstdint>
#include <set>
#include <utility>
#include <vector>
namespace beast {
namespace hash_metrics {
// Metrics for measuring the quality of container hash functions
/** Returns the fraction of duplicate items in the sequence. */
template <class FwdIter>
float
collision_factor (FwdIter first, FwdIter last)
{
std::set <typename FwdIter::value_type> s (first, last);
return 1 - static_cast <float>(s.size()) / std::distance (first, last);
}
//------------------------------------------------------------------------------
/** Returns the deviation of the sequence from the ideal distribution. */
template <class FwdIter>
float
distribution_factor (FwdIter first, FwdIter last)
{
using value_type = typename FwdIter::value_type;
static_assert (std::is_unsigned <value_type>::value, "");
const unsigned nbits = CHAR_BIT * sizeof(std::size_t);
const unsigned rows = nbits / 4;
unsigned counts[rows][16] = {};
std::for_each (first, last, [&](typename FwdIter::value_type h)
{
std::size_t mask = 0xF;
for (unsigned i = 0; i < rows; ++i, mask <<= 4)
counts[i][(h & mask) >> 4*i] += 1;
});
float mean_rows[rows] = {0};
float mean_cols[16] = {0};
for (unsigned i = 0; i < rows; ++i)
{
for (unsigned j = 0; j < 16; ++j)
{
mean_rows[i] += counts[i][j];
mean_cols[j] += counts[i][j];
}
}
for (unsigned i = 0; i < rows; ++i)
mean_rows[i] /= 16;
for (unsigned j = 0; j < 16; ++j)
mean_cols[j] /= rows;
std::pair<float, float> dev[rows][16];
for (unsigned i = 0; i < rows; ++i)
{
for (unsigned j = 0; j < 16; ++j)
{
dev[i][j].first = std::abs(counts[i][j] - mean_rows[i]) / mean_rows[i];
dev[i][j].second = std::abs(counts[i][j] - mean_cols[j]) / mean_cols[j];
}
}
float max_err = 0;
for (unsigned i = 0; i < rows; ++i)
{
for (unsigned j = 0; j < 16; ++j)
{
if (max_err < dev[i][j].first)
max_err = dev[i][j].first;
if (max_err < dev[i][j].second)
max_err = dev[i][j].second;
}
}
return max_err;
}
//------------------------------------------------------------------------------
namespace detail {
template <class T>
inline
T
sqr(T t)
{
return t*t;
}
double
score (int const* bins, std::size_t const bincount, double const k)
{
double const n = bincount;
// compute rms^2 value
double rms_sq = 0;
for(std::size_t i = 0; i < bincount; ++i)
rms_sq += sqr(bins[i]);;
rms_sq /= n;
// compute fill factor
double const f = (sqr(k) - 1) / (n*rms_sq - k);
// rescale to (0,1) with 0 = good, 1 = bad
return 1 - (f / n);
}
template <class T>
std::uint32_t
window (T* blob, int start, int count )
{
std::size_t const len = sizeof(T);
static_assert((len & 3) == 0, "");
if(count == 0)
return 0;
int const nbits = len * CHAR_BIT;
start %= nbits;
int ndwords = len / 4;
std::uint32_t const* k = static_cast <
std::uint32_t const*>(static_cast<void const*>(blob));
int c = start & (32-1);
int d = start / 32;
if(c == 0)
return (k[d] & ((1 << count) - 1));
int ia = (d + 1) % ndwords;
int ib = (d + 0) % ndwords;
std::uint32_t a = k[ia];
std::uint32_t b = k[ib];
std::uint32_t t = (a << (32-c)) | (b >> c);
t &= ((1 << count)-1);
return t;
}
} // detail
/** Calculated a windowed metric using bins.
TODO Need reference (SMHasher?)
*/
template <class FwdIter>
double
windowed_score (FwdIter first, FwdIter last)
{
auto const size (std::distance (first, last));
int maxwidth = 20;
// We need at least 5 keys per bin to reliably test distribution biases
// down to 1%, so don't bother to test sparser distributions than that
while (static_cast<double>(size) / (1ull << maxwidth) < 5.0)
maxwidth--;
double worst = 0;
std::vector <int> bins (1ull << maxwidth);
int const hashbits = sizeof(std::size_t) * CHAR_BIT;
for (int start = 0; start < hashbits; ++start)
{
int width = maxwidth;
bins.assign (1ull << width, 0);
for (auto iter (first); iter != last; ++iter)
++bins[detail::window(&*iter, start, width)];
// Test the distribution, then fold the bins in half,
// repeat until we're down to 256 bins
while (bins.size() >= 256)
{
double score (detail::score (
bins.data(), bins.size(), size));
worst = std::max(score, worst);
if (--width < 8)
break;
for (std::size_t i = 0, j = bins.size() / 2; j < bins.size(); ++i, ++j)
bins[i] += bins[j];
bins.resize(bins.size() / 2);
}
}
return worst;
}
} // hash_metrics
} // beast
#endif

View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <ripple/beast/hash/fnv1a.h>
#include <ripple/beast/hash/siphash.h>
#include <ripple/beast/hash/xxhasher.h>
#include <ripple/beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <random>
namespace beast {
class hash_speed_test : public beast::unit_test::suite
{
public:
template <class Generator>
static
void
rngfill (void* buffer, std::size_t bytes,
Generator& g)
{
using result_type =
typename Generator::result_type;
while (bytes >= sizeof(result_type))
{
auto const v = g();
std::memcpy(buffer, &v, sizeof(v));
buffer = reinterpret_cast<
std::uint8_t*>(buffer) + sizeof(v);
bytes -= sizeof(v);
}
if (bytes > 0)
{
auto const v = g();
std::memcpy(buffer, &v, bytes);
}
}
template <class Generator, std::size_t N,
class = std::enable_if_t<
N % sizeof(typename Generator::result_type) == 0>>
static
void
rngfill (std::array<std::uint8_t, N>& a, Generator& g)
{
using result_type =
typename Generator::result_type;
auto i = N / sizeof(result_type);
result_type* p =
reinterpret_cast<result_type*>(a.data());
while (i--)
*p++ = g();
}
using clock_type =
std::chrono::high_resolution_clock;
template <class Hasher, std::size_t KeySize>
void
test (std::string const& what, std::size_t n)
{
using namespace std;
using namespace std::chrono;
xor_shift_engine g(1);
array<std::uint8_t, KeySize> key;
auto const start = clock_type::now();
while(n--)
{
rngfill (key, g);
Hasher h;
h(key.data(), KeySize);
volatile size_t temp =
static_cast<std::size_t>(h);
(void)temp;
}
auto const elapsed = clock_type::now() - start;
log << setw(12) << what << " " <<
duration<double>(elapsed).count() << "s";
}
void
run()
{
enum
{
N = 100000000
};
#if ! BEAST_NO_XXHASH
test<xxhasher,32> ("xxhash", N);
#endif
test<fnv1a,32> ("fnv1a", N);
test<siphash,32> ("siphash", N);
pass();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(hash_speed,container,beast);
} // beast

View File

@@ -0,0 +1,47 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
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_HASH_UHASH_H_INCLUDED
#define BEAST_HASH_UHASH_H_INCLUDED
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/hash/spooky.h>
namespace beast {
// Universal hash function
template <class Hasher = spooky>
struct uhash
{
using result_type = typename Hasher::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
Hasher h;
hash_append (h, t);
return static_cast<result_type>(h);
}
};
} // beast
#endif

View File

@@ -0,0 +1,88 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, 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_HASH_XXHASHER_H_INCLUDED
#define BEAST_HASH_XXHASHER_H_INCLUDED
#ifndef BEAST_NO_XXHASH
#define BEAST_NO_XXHASH 0
#endif
#if ! BEAST_NO_XXHASH
#include <ripple/beast/hash/endian.h>
#include <ripple/beast/hash/impl/xxhash.h>
#include <type_traits>
#include <cstddef>
namespace beast {
class xxhasher
{
private:
// requires 64-bit std::size_t
static_assert(sizeof(std::size_t)==8, "");
detail::XXH64_state_t state_;
public:
using result_type = std::size_t;
static beast::endian const endian = beast::endian::native;
xxhasher() noexcept
{
detail::XXH64_reset (&state_, 1);
}
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
explicit
xxhasher (Seed seed)
{
detail::XXH64_reset (&state_, seed);
}
template <class Seed,
std::enable_if_t<
std::is_unsigned<Seed>::value>* = nullptr>
xxhasher (Seed seed, Seed)
{
detail::XXH64_reset (&state_, seed);
}
void
operator()(void const* key, std::size_t len) noexcept
{
detail::XXH64_update (&state_, key, len);
}
explicit
operator std::size_t() noexcept
{
return detail::XXH64_digest(&state_);
}
};
} // beast
#endif
#endif

View File

@@ -23,7 +23,7 @@
#include <ripple/beast/insight/Base.h>
#include <ripple/beast/insight/EventImpl.h>
#include <beast/clock/chrono_util.h>
#include <ripple/beast/clock/chrono_util.h>
#include <chrono>
#include <memory>

View File

@@ -19,7 +19,7 @@
#include <ripple/beast/insight/Group.h>
#include <ripple/beast/insight/Groups.h>
#include <beast/hash/uhash.h>
#include <ripple/beast/hash/uhash.h>
#include <unordered_map>
#include <memory>

View File

@@ -24,7 +24,7 @@
#include <ripple/beast/insight/GaugeImpl.h>
#include <ripple/beast/insight/MeterImpl.h>
#include <ripple/beast/insight/StatsDCollector.h>
#include <beast/asio/placeholders.h>
#include <beast/placeholders.hpp>
#include <ripple/beast/core/List.h>
#include <boost/asio/ip/tcp.hpp>
#include <boost/optional.hpp>

View File

@@ -22,8 +22,8 @@
#include <ripple/beast/net/IPAddressV4.h>
#include <ripple/beast/net/IPAddressV6.h>
#include <beast/hash/hash_append.h>
#include <beast/hash/uhash.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/hash/uhash.h>
#include <boost/functional/hash.hpp>
#include <cassert>
#include <cstdint>

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_NET_IPADDRESSV4_H_INCLUDED
#define BEAST_NET_IPADDRESSV4_H_INCLUDED
#include <beast/hash/hash_append.h>
#include <ripple/beast/hash/hash_append.h>
#include <cstdint>
#include <functional>

View File

@@ -21,8 +21,8 @@
#define BEAST_NET_IPENDPOINT_H_INCLUDED
#include <ripple/beast/net/IPAddress.h>
#include <beast/hash/hash_append.h>
#include <beast/hash/uhash.h>
#include <ripple/beast/hash/hash_append.h>
#include <ripple/beast/hash/uhash.h>
#include <cstdint>
#include <ios>
#include <string>

View File

@@ -1,195 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_HTTP_URL_H_INCLUDED
#define BEAST_HTTP_URL_H_INCLUDED
#include <ios>
#include <utility>
namespace beast {
/** A URL.
The accompanying robust parser is hardened against all forms of attack.
*/
class URL
{
public:
/** Construct a URL from it's components. */
URL (
std::string schema_,
std::string host_,
std::uint16_t port_,
std::string port_string_,
std::string path_,
std::string query_ = "",
std::string fragment_ = "",
std::string userinfo_ = "");
/** Construct an empty URL. */
explicit URL () = default;
/** Copy construct a URL. */
URL (URL const& other) = default;
/** Copy assign a URL. */
URL& operator= (URL const& other) = default;
/** Move construct a URL. */
URL (URL&& other) = default;
/** Returns `true` if this is an empty URL. */
bool
empty () const;
/** Returns the scheme of the URL.
If no scheme was specified, the string will be empty.
*/
std::string const&
scheme () const;
/** Returns the host of the URL.
If no host was specified, the string will be empty.
*/
std::string const&
host () const;
/** Returns the port number as an integer.
If no port was specified, the value will be zero.
*/
std::uint16_t
port () const;
/** Returns the port number as a string.
If no port was specified, the string will be empty.
*/
std::string const&
port_string () const;
/** Returns the path of the URL.
If no path was specified, the string will be empty.
*/
std::string const&
path () const;
/** Returns the query parameters portion of the URL.
If no query parameters were present, the string will be empty.
*/
std::string const&
query () const;
/** Returns the URL fragment, if any. */
std::string const&
fragment () const;
/** Returns the user information, if any. */
std::string const&
userinfo () const;
private:
std::string m_scheme;
std::string m_host;
std::uint16_t m_port = 0;
std::string m_port_string;
std::string m_path;
std::string m_query;
std::string m_fragment;
std::string m_userinfo;
};
/** Attempt to parse a string into a URL */
std::pair<bool, URL>
parse_URL(std::string const&);
/** Retrieve the full URL as a single string. */
std::string
to_string(URL const& url);
/** Output stream conversion. */
std::ostream&
operator<< (std::ostream& os, URL const& url);
/** URL comparisons. */
/** @{ */
inline bool
operator== (URL const& lhs, URL const& rhs)
{
return to_string (lhs) == to_string (rhs);
}
inline bool
operator!= (URL const& lhs, URL const& rhs)
{
return to_string (lhs) != to_string (rhs);
}
inline bool
operator< (URL const& lhs, URL const& rhs)
{
return to_string (lhs) < to_string (rhs);
}
inline bool operator> (URL const& lhs, URL const& rhs)
{
return to_string (rhs) < to_string (lhs);
}
inline bool
operator<= (URL const& lhs, URL const& rhs)
{
return ! (to_string (rhs) < to_string (lhs));
}
inline bool
operator>= (URL const& lhs, URL const& rhs)
{
return ! (to_string (lhs) < to_string (rhs));
}
/** @} */
/** boost::hash support */
template <class Hasher>
inline
void
hash_append (Hasher& h, URL const& url)
{
using beast::hash_append;
hash_append (h, to_string (url));
}
}
//------------------------------------------------------------------------------
namespace std {
template <>
struct hash <beast::URL>
{
std::size_t operator() (beast::URL const& url) const
{
return std::hash<std::string>{} (to_string (url));
}
};
}
//------------------------------------------------------------------------------
#endif

View File

@@ -1,231 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/beast/net/URL.h>
#include <beast/http/src/nodejs_parser.h>
namespace beast {
URL::URL (
std::string scheme_,
std::string host_,
std::uint16_t port_,
std::string port_string_,
std::string path_,
std::string query_,
std::string fragment_,
std::string userinfo_)
: m_scheme (scheme_)
, m_host (host_)
, m_port (port_)
, m_port_string (port_string_)
, m_path (path_)
, m_query (query_)
, m_fragment (fragment_)
, m_userinfo (userinfo_)
{
}
//------------------------------------------------------------------------------
bool
URL::empty () const
{
return m_scheme.empty ();
}
std::string
const& URL::scheme () const
{
return m_scheme;
}
std::string
const& URL::host () const
{
return m_host;
}
std::string
const& URL::port_string () const
{
return m_port_string;
}
std::uint16_t
URL::port () const
{
return m_port;
}
std::string
const& URL::path () const
{
return m_path;
}
std::string
const& URL::query () const
{
return m_query;
}
std::string
const& URL::fragment () const
{
return m_fragment;
}
std::string
const& URL::userinfo () const
{
return m_userinfo;
}
//------------------------------------------------------------------------------
std::pair<bool, URL>
parse_URL(std::string const& url)
{
std::size_t const buflen (url.size ());
char const* const buf (url.c_str ());
http_parser_url parser;
if (http_parser_parse_url (buf, buflen, false, &parser) != 0)
return std::make_pair (false, URL{});
std::string scheme;
std::string host;
std::uint16_t port (0);
std::string port_string;
std::string path;
std::string query;
std::string fragment;
std::string userinfo;
if ((parser.field_set & (1<<UF_SCHEMA)) != 0)
{
scheme = std::string (
buf + parser.field_data [UF_SCHEMA].off,
parser.field_data [UF_SCHEMA].len);
}
if ((parser.field_set & (1<<UF_HOST)) != 0)
{
host = std::string (
buf + parser.field_data [UF_HOST].off,
parser.field_data [UF_HOST].len);
}
if ((parser.field_set & (1<<UF_PORT)) != 0)
{
port = parser.port;
port_string = std::string (
buf + parser.field_data [UF_PORT].off,
parser.field_data [UF_PORT].len);
}
if ((parser.field_set & (1<<UF_PATH)) != 0)
{
path = std::string (
buf + parser.field_data [UF_PATH].off,
parser.field_data [UF_PATH].len);
}
if ((parser.field_set & (1<<UF_QUERY)) != 0)
{
query = std::string (
buf + parser.field_data [UF_QUERY].off,
parser.field_data [UF_QUERY].len);
}
if ((parser.field_set & (1<<UF_FRAGMENT)) != 0)
{
fragment = std::string (
buf + parser.field_data [UF_FRAGMENT].off,
parser.field_data [UF_FRAGMENT].len);
}
if ((parser.field_set & (1<<UF_USERINFO)) != 0)
{
userinfo = std::string (
buf + parser.field_data [UF_USERINFO].off,
parser.field_data [UF_USERINFO].len);
}
return std::make_pair (true,
URL {scheme, host, port, port_string, path, query, fragment, userinfo});
}
std::string
to_string (URL const& url)
{
std::string s;
if (!url.empty ())
{
// Pre-allocate enough for components and inter-component separators
s.reserve (
url.scheme ().length () + url.userinfo ().length () +
url.host ().length () + url.port_string ().length () +
url.query ().length () + url.fragment ().length () + 16);
s.append (url.scheme ());
s.append ("://");
if (!url.userinfo ().empty ())
{
s.append (url.userinfo ());
s.append ("@");
}
s.append (url.host ());
if (url.port ())
{
s.append (":");
s.append (url.port_string ());
}
s.append (url.path ());
if (!url.query ().empty ())
{
s.append ("?");
s.append (url.query ());
}
if (!url.fragment ().empty ())
{
s.append ("#");
s.append (url.fragment ());
}
}
return s;
}
std::ostream&
operator<< (std::ostream &os, URL const& url)
{
os << to_string (url);
return os;
}
}

View File

@@ -26,7 +26,7 @@
#include <ripple/beast/net/IPEndpoint.h>
#include <ripple/beast/net/detail/Parse.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <typeinfo>

View File

@@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <ripple/beast/asio/ssl_error.h>
#include <ripple/beast/unit_test.h>
#include <string>
namespace beast {
class error_test : public unit_test::suite
{
public:
void run()
{
{
boost::system::error_code ec =
boost::system::error_code (335544539,
boost::asio::error::get_ssl_category ());
std::string const s = beast::error_message_with_ssl(ec);
expect(s == " (20,0,219) error:140000DB:SSL routines:SSL routines:short read");
}
}
};
BEAST_DEFINE_TESTSUITE(error,asio,beast);
} // beast

View File

@@ -18,9 +18,9 @@
//==============================================================================
#include <ripple/beast/nudb/test/common.h>
#include <beast/unit_test/temp_dir.h>
#include <beast/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <beast/detail/temp_dir.hpp>
#include <ripple/beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <cmath>
#include <cstring>
#include <memory>
@@ -98,7 +98,7 @@ public:
testcase (abort_on_fail);
beast::temp_dir tempDir;
beast::detail::temp_dir tempDir;
do_test (N, tempDir.path());
}
};

View File

@@ -18,9 +18,9 @@
//==============================================================================
#include <ripple/beast/nudb/test/common.h>
#include <beast/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <beast/unit_test/temp_dir.h>
#include <ripple/beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <beast/detail/temp_dir.hpp>
#include <cmath>
#include <cstring>
#include <memory>
@@ -117,7 +117,7 @@ public:
{
testcase << count << " inserts";
beast::temp_dir tempDir;
beast::detail::temp_dir tempDir;
auto const path = tempDir.path();
for (std::size_t n = 1;;++n)

View File

@@ -18,9 +18,9 @@
//==============================================================================
#include <ripple/beast/nudb/test/common.h>
#include <beast/unit_test/temp_dir.h>
#include <beast/xor_shift_engine.h>
#include <beast/unit_test/suite.h>
#include <beast/detail/temp_dir.hpp>
#include <ripple/beast/xor_shift_engine.h>
#include <ripple/beast/unit_test.h>
#include <cmath>
#include <iomanip>
#include <memory>
@@ -44,7 +44,7 @@ public:
std::size_t block_size, float load_factor)
{
testcase (abort_on_fail);
beast::temp_dir tempDir;
beast::detail::temp_dir tempDir;
auto const dp = tempDir.file ("nudb.dat");
auto const kp = tempDir.file ("nudb.key");

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <ripple/beast/nudb/detail/varint.h>
#include <beast/unit_test/suite.h>
#include <ripple/beast/unit_test.h>
#include <array>
#include <vector>

View File

@@ -19,8 +19,8 @@
#include <ripple/beast/nudb/verify.h>
#include <ripple/beast/nudb/test/common.h>
#include <beast/unit_test/suite.h>
#include <beast/clock/basic_seconds_clock.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <chrono>
#include <iomanip>
#include <ostream>

View File

@@ -23,8 +23,8 @@
#include <ripple/beast/nudb.h>
#include <ripple/beast/nudb/identity.h>
#include <ripple/beast/nudb/test/fail_file.h>
#include <beast/hash/xxhasher.h>
#include <beast/xor_shift_engine.h>
#include <ripple/beast/hash/xxhasher.h>
#include <ripple/beast/xor_shift_engine.h>
#include <cstdint>
#include <iomanip>
#include <memory>

View File

@@ -0,0 +1,188 @@
# Beast.py
# Copyright 2014 by:
# Vinnie Falco <vinnie.falco@gmail.com>
# Tom Ritchford <?>
# Nik Bougalis <?>
# This file is part of Beast: http://github.com/vinniefalco/Beast
from __future__ import absolute_import, division, print_function, unicode_literals
import os
import platform
import subprocess
import sys
import SCons.Node
import SCons.Util
#-------------------------------------------------------------------------------
#
# Environment
#
#-------------------------------------------------------------------------------
def _execute(args, include_errors=True, **kwds):
"""Execute a shell command and return the value. If args is a string,
it's split on spaces - if some of your arguments contain spaces, args should
instead be a list of arguments."""
def single_line(line, report_errors=True, joiner='+'):
"""Force a string to be a single line with no carriage returns, and report
a warning if there was more than one line."""
lines = line.strip().splitlines()
if report_errors and len(lines) > 1:
print('multiline result:', lines)
return joiner.join(lines)
def is_string(s):
"""Is s a string? - in either Python 2.x or 3.x."""
return isinstance(s, (str, unicode))
if is_string(args):
args = args.split()
stderr = subprocess.STDOUT if include_errors else None
return single_line(subprocess.check_output(args, stderr=stderr, **kwds))
class __System(object):
"""Provides information about the host platform"""
def __init__(self):
self.name = platform.system()
self.linux = self.name == 'Linux'
self.osx = self.name == 'Darwin'
self.windows = self.name == 'Windows'
self.distro = None
self.version = None
# True if building under the Travis CI (http://travis-ci.org)
self.travis = (
os.environ.get('TRAVIS', '0') == 'true') and (
os.environ.get('CI', '0') == 'true')
if self.linux:
self.distro, self.version, _ = platform.linux_distribution()
self.__display = '%s %s (%s)' % (self.distro, self.version, self.name)
elif self.osx:
parts = platform.mac_ver()[0].split('.')
while len(parts) < 3:
parts.append('0')
self.__display = '%s %s' % (self.name, '.'.join(parts))
elif self.windows:
release, version, csd, ptype = platform.win32_ver()
self.__display = '%s %s %s (%s)' % (self.name, release, version, ptype)
else:
raise Exception('Unknown system platform "' + self.name + '"')
self.platform = self.distro or self.name
def __str__(self):
return self.__display
class Git(object):
"""Provides information about git and the repository we are called from"""
def __init__(self, env):
self.tags = self.branch = self.user = ''
self.exists = env.Detect('git')
if self.exists:
try:
self.tags = _execute('git describe --tags')
self.branch = _execute('git rev-parse --abbrev-ref HEAD')
remote = _execute('git config remote.origin.url')
self.user = remote.split(':')[1].split('/')[0]
except:
self.exists = False
system = __System()
#-------------------------------------------------------------------------------
def printChildren(target):
def doPrint(tgt, level, found):
for item in tgt:
if SCons.Util.is_List(item):
doPrint(item, level, found)
else:
if item.abspath in found:
continue
found[item.abspath] = False
print('\t'*level + item.path)
#DoPrint(item.children(scan=1), level+1, found)
item.scan()
doPrint(item.all_children(), level+1, found)
doPrint(target, 0, {})
def variantFile(path, variant_dirs):
'''Returns the path to the corresponding dict entry in variant_dirs'''
path = str(path)
for dest, source in variant_dirs.iteritems():
common = os.path.commonprefix([path, source])
if common == source:
return os.path.join(dest, path[len(common)+1:])
return path
def variantFiles(files, variant_dirs):
'''Returns a list of files remapped to their variant directories'''
result = []
for path in files:
result.append(variantFile(path, variant_dirs))
return result
def printEnv(env, keys):
if type(keys) != list:
keys = list(keys)
s = ''
for key in keys:
if key in env:
value = env[key]
else:
value = ''
s+=('%s=%s, ' % (key, value))
print('[' + s + ']')
#-------------------------------------------------------------------------------
#
# Output
#
#-------------------------------------------------------------------------------
# See https://stackoverflow.com/questions/7445658/how-to-detect-if-the-console-does-support-ansi-escape-codes-in-python
CAN_CHANGE_COLOR = (
hasattr(sys.stderr, "isatty")
and sys.stderr.isatty()
and not system.windows
and not os.environ.get('INSIDE_EMACS')
)
# See https://en.wikipedia.org/wiki/ANSI_escape_code
BLUE = 94
GREEN = 92
RED = 91
YELLOW = 93
def add_mode(text, *modes):
if CAN_CHANGE_COLOR:
modes = ';'.join(str(m) for m in modes)
return '\033[%sm%s\033[0m' % (modes, text)
else:
return text
def blue(text):
return add_mode(text, BLUE)
def green(text):
return add_mode(text, GREEN)
def red(text):
return add_mode(text, RED)
def yellow(text):
return add_mode(text, YELLOW)
def warn(text, print=print):
print('%s %s' % (red('WARNING:'), text))
# Prints command lines using environment substitutions
def print_coms(coms, env):
if type(coms) is str:
coms=list(coms)
for key in coms:
cmdline = env.subst(env[key], 0,
env.File('<target>'), env.File('<sources>'))
print (green(cmdline))

View File

@@ -0,0 +1,97 @@
#
# Copyright (c) 2009 Scott Stafford
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Author : Scott Stafford
# Date : 2009-12-09 20:36:14
#
# Changes : Vinnie Falco <vinnie.falco@gmail.com>
# Date : 2014--4-25
"""
Protoc.py: Protoc Builder for SCons
This Builder invokes protoc to generate C++ and Python from a .proto file.
NOTE: Java is not currently supported.
"""
__author__ = "Scott Stafford"
import SCons.Action
import SCons.Builder
import SCons.Defaults
import SCons.Node.FS
import SCons.Util
from SCons.Script import File, Dir
import os.path
protocs = 'protoc'
ProtocAction = SCons.Action.Action('$PROTOCCOM', '$PROTOCCOMSTR')
def ProtocEmitter(target, source, env):
PROTOCOUTDIR = env['PROTOCOUTDIR']
PROTOCPYTHONOUTDIR = env['PROTOCPYTHONOUTDIR']
for source_path in [str(x) for x in source]:
base = os.path.splitext(os.path.basename(source_path))[0]
if PROTOCOUTDIR:
target.extend([os.path.join(PROTOCOUTDIR, base + '.pb.cc'),
os.path.join(PROTOCOUTDIR, base + '.pb.h')])
if PROTOCPYTHONOUTDIR:
target.append(os.path.join(PROTOCPYTHONOUTDIR, base + '_pb2.py'))
try:
target.append(env['PROTOCFDSOUT'])
except KeyError:
pass
#print "PROTOC SOURCE:", [str(s) for s in source]
#print "PROTOC TARGET:", [str(s) for s in target]
return target, source
ProtocBuilder = SCons.Builder.Builder(
action = ProtocAction,
emitter = ProtocEmitter,
srcsuffix = '$PROTOCSRCSUFFIX')
def generate(env):
"""Add Builders and construction variables for protoc to an Environment."""
try:
bld = env['BUILDERS']['Protoc']
except KeyError:
bld = ProtocBuilder
env['BUILDERS']['Protoc'] = bld
env['PROTOC'] = env.Detect(protocs) or 'protoc'
env['PROTOCFLAGS'] = SCons.Util.CLVar('')
env['PROTOCPROTOPATH'] = SCons.Util.CLVar('')
env['PROTOCCOM'] = '$PROTOC ${["-I%s"%x for x in PROTOCPROTOPATH]} $PROTOCFLAGS --cpp_out=$PROTOCCPPOUTFLAGS$PROTOCOUTDIR ${PROTOCPYTHONOUTDIR and ("--python_out="+PROTOCPYTHONOUTDIR) or ""} ${PROTOCFDSOUT and ("-o"+PROTOCFDSOUT) or ""} ${SOURCES}'
env['PROTOCOUTDIR'] = '${SOURCE.dir}'
env['PROTOCPYTHONOUTDIR'] = "python"
env['PROTOCSRCSUFFIX'] = '.proto'
def exists(env):
return env.Detect(protocs)

View File

@@ -0,0 +1,894 @@
# Copyright 2014 Vinnie Falco (vinnie.falco@gmail.com)
# Portions Copyright The SCons Foundation
# Portions Copyright Google, Inc.
# This file is part of beast
"""
A SCons tool to provide a family of scons builders that
generate Visual Studio project files
"""
import collections
import hashlib
import io
import itertools
import ntpath
import os
import pprint
import random
import re
import SCons.Builder
import SCons.Node.FS
import SCons.Node
import SCons.Script.Main
import SCons.Util
#-------------------------------------------------------------------------------
# Adapted from msvs.py
UnicodeByteMarker = '\xEF\xBB\xBF'
V14DSPHeader = """\
<?xml version="1.0" encoding="%(encoding)s"?>\r
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
"""
V14DSPProjectConfiguration = """\
<ProjectConfiguration Include="%(variant)s|%(platform)s">\r
<Configuration>%(variant)s</Configuration>\r
<Platform>%(platform)s</Platform>\r
</ProjectConfiguration>\r
"""
V14DSPGlobals = """\
<PropertyGroup Label="Globals">\r
<ProjectGuid>%(project_guid)s</ProjectGuid>\r
<Keyword>Win32Proj</Keyword>\r
<RootNamespace>%(name)s</RootNamespace>\r
<IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>\r
</PropertyGroup>\r
"""
V14DSPPropertyGroup = """\
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'" Label="Configuration">\r
<CharacterSet>MultiByte</CharacterSet>\r
<ConfigurationType>Application</ConfigurationType>\r
<PlatformToolset>v140</PlatformToolset>\r
<LinkIncremental>False</LinkIncremental>\r
<UseDebugLibraries>%(use_debug_libs)s</UseDebugLibraries>\r
<UseOfMfc>False</UseOfMfc>\r
<WholeProgramOptimization>false</WholeProgramOptimization>\r
<IntDir>%(int_dir)s</IntDir>\r
<OutDir>%(out_dir)s</OutDir>\r
</PropertyGroup>\r
"""
V14DSPImportGroup= """\
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'" Label="PropertySheets">\r
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
</ImportGroup>\r
"""
V14DSPItemDefinitionGroup= """\
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'">\r
"""
V14CustomBuildProtoc= """\
<FileType>Document</FileType>\r
<Command Condition="'$(Configuration)|$(Platform)'=='%(name)s'">protoc --cpp_out=%(cpp_out)s --proto_path=%%(RelativeDir) %%(Identity)</Command>\r
<Outputs Condition="'$(Configuration)|$(Platform)'=='%(name)s'">%(base_out)s.pb.h;%(base_out)s.pb.cc</Outputs>\r
<Message Condition="'$(Configuration)|$(Platform)'=='%(name)s'">protoc --cpp_out=%(cpp_out)s --proto_path=%%(RelativeDir) %%(Identity)</Message>\r
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='%(name)s'">false</LinkObjects>\r
"""
V14DSPFiltersHeader = (
'''<?xml version="1.0" encoding="utf-8"?>\r
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
''')
#-------------------------------------------------------------------------------
def is_subdir(child, parent):
'''Determine if child is a subdirectory of parent'''
return os.path.commonprefix([parent, child]) == parent
def _key(item):
if isinstance(item, (str, unicode)):
return ('s', item.upper(), item)
elif isinstance(item, (int, long, float)):
return ('n', item)
elif isinstance(item, (list, tuple)):
return ('l', map(_key, item))
elif isinstance(item, dict):
return ('d', xsorted(item.keys()), xsorted(item.values()))
elif isinstance(item, Configuration):
return ('c', _key(item.name), _key(item.target), _key(item.variant), _key(item.platform))
elif isinstance(item, Item):
return ('i', _key(winpath(item.path())), _key(item.is_compiled()), _key(item.builder()), _key(item.tag()), _key(item.is_excluded()))
elif isinstance(item, SCons.Node.FS.File):
return ('f', _key(item.name), _key(item.suffix))
else:
return ('x', item)
def xsorted(tosort, **kwargs):
'''Performs sorted in a deterministic manner.'''
if 'key' in kwargs:
map(kwargs['key'], tosort)
kwargs['key'] = _key
return sorted(tosort, **kwargs)
def itemList(items, sep):
if type(items) == str: # Won't work in Python 3.
return items
def gen():
for item in xsorted(items):
if isinstance(item, dict):
for k, v in xsorted(item.items()):
yield k + '=' + v
elif isinstance(item, (tuple, list)):
assert len(item) == 2, "Item shoud have exactly two elements: " + str(item)
yield '%s=%s' % tuple(item)
else:
yield item
yield sep
return ''.join(gen())
#-------------------------------------------------------------------------------
class SwitchConverter(object):
'''Converts command line switches to MSBuild XML, using tables'''
def __init__(self, table, booltable, retable=None):
self.table = {}
for key in table:
self.table[key] = table[key]
for key in booltable:
value = booltable[key]
self.table[key] = [value[0], 'True']
self.table[key + '-'] = [value[0], 'False']
if retable != None:
self.retable = retable
else:
self.retable = []
def getXml(self, switches, prefix = ''):
switches = list(set(switches)) # Filter dupes because on windows platforms, /nologo is added automatically to the environment.
xml = []
for regex, tag in self.retable:
matches = []
for switch in switches[:]:
match = regex.match(switch)
if None != match:
matches.append(match.group(1))
switches.remove(switch)
if len(matches) > 0:
xml.append (
'%s<%s>%s</%s>\r\n' % (
prefix, tag, ';'.join(matches), tag))
unknown = []
for switch in switches:
try:
value = self.table[switch]
xml.append (
'%s<%s>%s</%s>\r\n' % (
prefix, value[0], value[1], value[0]))
except:
unknown.append(switch)
if unknown:
s = itemList(unknown, ' ')
tag = 'AdditionalOptions'
xml.append('%(prefix)s<%(tag)s>%(s)s%%(%(tag)s)</%(tag)s>\r\n' % locals())
if xml:
return ''.join(xml)
return ''
class ClSwitchConverter(SwitchConverter):
def __init__(self):
booltable = {
'/C' : ['KeepComments'],
'/doc' : ['GenerateXMLDocumentationFiles'],
'/FAu' : ['UseUnicodeForAssemblerListing'],
'/FC' : ['UseFullPaths'],
'/FR' : ['BrowseInformation'],
'/Fr' : ['BrowseInformation'],
'/Fx' : ['ExpandAttributedSource'],
'/GF' : ['StringPooling'],
'/GL' : ['WholeProgramOptimization'],
'/Gm' : ['MinimalRebuild'],
'/GR' : ['RuntimeTypeInfo'],
'/GS' : ['BufferSecurityCheck'],
'/GT' : ['EnableFiberSafeOptimizations'],
'/Gy' : ['FunctionLevelLinking'],
'/MP' : ['MultiProcessorCompilation'],
'/Oi' : ['IntrinsicFunctions'],
'/Oy' : ['OmitFramePointers'],
'/RTCc' : ['SmallerTypeCheck'],
'/u' : ['UndefineAllPreprocessorDefinitions'],
'/X' : ['IgnoreStandardIncludePath'],
'/WX' : ['TreatWarningAsError'],
'/Za' : ['DisableLanguageExtensions'],
'/Zl' : ['OmitDefaultLibName'],
'/fp:except' : ['FloatingPointExceptions'],
'/hotpatch' : ['CreateHotpatchableImage'],
'/nologo' : ['SuppressStartupBanner'],
'/openmp' : ['OpenMPSupport'],
'/showIncludes' : ['ShowIncludes'],
'/Zc:forScope' : ['ForceConformanceInForLoopScope'],
'/Zc:wchar_t' : ['TreatWChar_tAsBuiltInType'],
}
table = {
'/EHsc' : ['ExceptionHandling', 'Sync'],
'/EHa' : ['ExceptionHandling', 'Async'],
'/EHs' : ['ExceptionHandling', 'SyncCThrow'],
'/FA' : ['AssemblerOutput', 'AssemblyCode'],
'/FAcs' : ['AssemblerOutput', 'All'],
'/FAc' : ['AssemblerOutput', 'AssemblyAndMachineCode'],
'/FAs' : ['AssemblerOutput', 'AssemblyAndSourceCode'],
'/Gd' : ['CallingConvention', 'Cdecl'],
'/Gr' : ['CallingConvention', 'FastCall'],
'/Gz' : ['CallingConvention', 'StdCall'],
'/MT' : ['RuntimeLibrary', 'MultiThreaded'],
'/MTd' : ['RuntimeLibrary', 'MultiThreadedDebug'],
'/MD' : ['RuntimeLibrary', 'MultiThreadedDLL'],
'/MDd' : ['RuntimeLibrary', 'MultiThreadedDebugDLL'],
'/Od' : ['Optimization', 'Disabled'],
'/O1' : ['Optimization', 'MinSpace'],
'/O2' : ['Optimization', 'MaxSpeed'],
'/Ox' : ['Optimization', 'Full'],
'/Ob1' : ['InlineFunctionExpansion', 'OnlyExplicitInline'],
'/Ob2' : ['InlineFunctionExpansion', 'AnySuitable'],
'/Ot' : ['FavorSizeOrSpeed', 'Speed'],
'/Os' : ['FavorSizeOrSpeed', 'Size'],
'/RTCs' : ['BasicRuntimeChecks', 'StackFrameRuntimeCheck'],
'/RTCu' : ['BasicRuntimeChecks', 'UninitializedLocalUsageCheck'],
'/RTC1' : ['BasicRuntimeChecks', 'EnableFastChecks'],
'/TC' : ['CompileAs', 'CompileAsC'],
'/TP' : ['CompileAs', 'CompileAsCpp'],
'/W0' : [ 'WarningLevel', 'TurnOffAllWarnings'],
'/W1' : [ 'WarningLevel', 'Level1'],
'/W2' : [ 'WarningLevel', 'Level2'],
'/W3' : [ 'WarningLevel', 'Level3'],
'/W4' : [ 'WarningLevel', 'Level4'],
'/Wall' : [ 'WarningLevel', 'EnableAllWarnings'],
'/Yc' : ['PrecompiledHeader', 'Create'],
'/Yu' : ['PrecompiledHeader', 'Use'],
'/Z7' : ['DebugInformationFormat', 'OldStyle'],
'/Zi' : ['DebugInformationFormat', 'ProgramDatabase'],
'/ZI' : ['DebugInformationFormat', 'EditAndContinue'],
'/Zp1' : ['StructMemberAlignment', '1Byte'],
'/Zp2' : ['StructMemberAlignment', '2Bytes'],
'/Zp4' : ['StructMemberAlignment', '4Bytes'],
'/Zp8' : ['StructMemberAlignment', '8Bytes'],
'/Zp16' : ['StructMemberAlignment', '16Bytes'],
'/arch:IA32' : ['EnableEnhancedInstructionSet', 'NoExtensions'],
'/arch:SSE' : ['EnableEnhancedInstructionSet', 'StreamingSIMDExtensions'],
'/arch:SSE2' : ['EnableEnhancedInstructionSet', 'StreamingSIMDExtensions2'],
'/arch:AVX' : ['EnableEnhancedInstructionSet', 'AdvancedVectorExtensions'],
'/clr' : ['CompileAsManaged', 'True'],
'/clr:pure' : ['CompileAsManaged', 'Pure'],
'/clr:safe' : ['CompileAsManaged', 'Safe'],
'/clr:oldSyntax' : ['CompileAsManaged', 'OldSyntax'],
'/fp:fast' : ['FloatingPointModel', 'Fast'],
'/fp:precise' : ['FloatingPointModel', 'Precise'],
'/fp:strict' : ['FloatingPointModel', 'Strict'],
'/errorReport:none' : ['ErrorReporting', 'None'],
'/errorReport:prompt' : ['ErrorReporting', 'Prompt'],
'/errorReport:queue' : ['ErrorReporting', 'Queue'],
'/errorReport:send' : ['ErrorReporting', 'Send'],
}
retable = [
(re.compile(r'/wd\"(\d+)\"'), 'DisableSpecificWarnings'),
]
# Ideas from Google's Generate Your Project
'''
_Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I
_Same(_compile, 'PreprocessorDefinitions', _string_list) # /D
_Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd
_Same(_compile, 'AdditionalOptions', _string_list)
_Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI
_Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa
_Same(_compile, 'BrowseInformationFile', _file_name)
_Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI
_Same(_compile, 'ForcedUsingFiles', _file_list) # /FU
_Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U
_Same(_compile, 'XMLDocumentationFileName', _file_name)
'' : ['EnablePREfast', _boolean) # /analyze Visible='false'
_Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo
_Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile',
_file_name) # Used with /Yc and /Yu
_Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile',
_file_name) # /Fp
_ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J')
_MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors
_MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name)
_MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we
_MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi
'''
SwitchConverter.__init__(self, table, booltable, retable)
class LinkSwitchConverter(SwitchConverter):
def __init__(self):
# Based on code in Generate Your Project
booltable = {
'/DEBUG' : ['GenerateDebugInformation'],
'/DYNAMICBASE' : ['RandomizedBaseAddress'],
'/NOLOGO' : ['SuppressStartupBanner'],
'/nologo' : ['SuppressStartupBanner'],
}
table = {
'/ERRORREPORT:NONE' : ['ErrorReporting', 'NoErrorReport'],
'/ERRORREPORT:PROMPT' : ['ErrorReporting', 'PromptImmediately'],
'/ERRORREPORT:QUEUE' : ['ErrorReporting', 'QueueForNextLogin'],
'/ERRORREPORT:SEND' : ['ErrorReporting', 'SendErrorReport'],
'/MACHINE:X86' : ['TargetMachine', 'MachineX86'],
'/MACHINE:ARM' : ['TargetMachine', 'MachineARM'],
'/MACHINE:EBC' : ['TargetMachine', 'MachineEBC'],
'/MACHINE:IA64' : ['TargetMachine', 'MachineIA64'],
'/MACHINE:MIPS' : ['TargetMachine', 'MachineMIPS'],
'/MACHINE:MIPS16' : ['TargetMachine', 'MachineMIPS16'],
'/MACHINE:MIPSFPU' : ['TargetMachine', 'MachineMIPSFPU'],
'/MACHINE:MIPSFPU16' : ['TargetMachine', 'MachineMIPSFPU16'],
'/MACHINE:SH4' : ['TargetMachine', 'MachineSH4'],
'/MACHINE:THUMB' : ['TargetMachine', 'MachineTHUMB'],
'/MACHINE:X64' : ['TargetMachine', 'MachineX64'],
'/NXCOMPAT' : ['DataExecutionPrevention', 'true'],
'/NXCOMPAT:NO' : ['DataExecutionPrevention', 'false'],
'/SUBSYSTEM:CONSOLE' : ['SubSystem', 'Console'],
'/SUBSYSTEM:WINDOWS' : ['SubSystem', 'Windows'],
'/SUBSYSTEM:NATIVE' : ['SubSystem', 'Native'],
'/SUBSYSTEM:EFI_APPLICATION' : ['SubSystem', 'EFI Application'],
'/SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER' : ['SubSystem', 'EFI Boot Service Driver'],
'/SUBSYSTEM:EFI_ROM' : ['SubSystem', 'EFI ROM'],
'/SUBSYSTEM:EFI_RUNTIME_DRIVER' : ['SubSystem', 'EFI Runtime'],
'/SUBSYSTEM:WINDOWSCE' : ['SubSystem', 'WindowsCE'],
'/SUBSYSTEM:POSIX' : ['SubSystem', 'POSIX'],
}
'''
/TLBID:1 /MANIFEST /MANIFESTUAC:level='asInvoker' uiAccess='false'
_Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION
_Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK
_Same(_link, 'DelaySign', _boolean) # /DELAYSIGN
_Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC
_Same(_link, 'GenerateMapFile', _boolean) # /MAP
_Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
_Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL
_Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS
_Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED
_Same(_link, 'PerUserRedirection', _boolean)
_Same(_link, 'Profile', _boolean) # /PROFILE
_Same(_link, 'RegisterOutput', _boolean)
_Same(_link, 'SetChecksum', _boolean) # /RELEASE
_Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD
_Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD
_Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY
_Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true'
_Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF
_Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED
_Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE
_Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF
_Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE
_Same(_link, 'AdditionalDependencies', _file_list)
_Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
_Same(_link, 'AdditionalManifestDependencies', _file_list) # /MANIFESTDEPENDENCY:
_Same(_link, 'AdditionalOptions', _string_list)
_Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE
_Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE
_Same(_link, 'BaseAddress', _string) # /BASE
_Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD
_Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE
_Same(_link, 'EntryPointSymbol', _string) # /ENTRY
_Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE
_Same(_link, 'FunctionOrder', _file_name) # /ORDER
_Same(_link, 'HeapCommitSize', _string)
_Same(_link, 'HeapReserveSize', _string) # /HEAP
_Same(_link, 'ImportLibrary', _file_name) # /IMPLIB
_Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER
_Same(_link, 'KeyFile', _file_name) # /KEYFILE
_Same(_link, 'ManifestFile', _file_name) # /ManifestFile
_Same(_link, 'MapFileName', _file_name)
_Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT
_Same(_link, 'MergeSections', _string) # /MERGE
_Same(_link, 'MidlCommandFile', _file_name) # /MIDL
_Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF
_Same(_link, 'OutputFile', _file_name) # /OUT
_Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD
_Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB
_Same(_link, 'StackCommitSize', _string)
_Same(_link, 'StackReserveSize', _string) # /STACK
_Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT
_Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID
_Same(_link, 'Version', _string) # /VERSION
_Same(_link, 'AssemblyDebug',
_Enumeration(['',
'true', # /ASSEMBLYDEBUG
'false'])) # /ASSEMBLYDEBUG:DISABLE
_Same(_link, 'CLRImageType',
_Enumeration(['Default',
'ForceIJWImage', # /CLRIMAGETYPE:IJW
'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE
'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE
_Same(_link, 'CLRThreadAttribute',
_Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE
'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA
'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA
_Same(_link, 'Driver',
_Enumeration(['NotSet',
'Driver', # /Driver
'UpOnly', # /DRIVER:UPONLY
'WDM'])) # /DRIVER:WDM
_Same(_link, 'LinkTimeCodeGeneration',
_Enumeration(['Default',
'UseLinkTimeCodeGeneration', # /LTCG
'PGInstrument', # /LTCG:PGInstrument
'PGOptimization', # /LTCG:PGOptimize
'PGUpdate'])) # /LTCG:PGUpdate
_Same(_link, 'ShowProgress',
_Enumeration(['NotSet',
'LinkVerbose', # /VERBOSE
'LinkVerboseLib'], # /VERBOSE:Lib
new=['LinkVerboseICF', # /VERBOSE:ICF
'LinkVerboseREF', # /VERBOSE:REF
'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH
'LinkVerboseCLR'])) # /VERBOSE:CLR
_Same(_link, 'UACExecutionLevel',
_Enumeration(['AsInvoker', # /level='asInvoker'
'HighestAvailable', # /level='highestAvailable'
'RequireAdministrator'])) # /level='requireAdministrator'
_Same(_link, 'MinimumRequiredVersion', _string)
_Same(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX
# Options found in MSVS that have been renamed in MSBuild.
_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries',
_file_list) # /NODEFAULTLIB
_Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY
_Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET
_Moved(_link, 'GenerateManifest', '', _boolean)
_Moved(_link, 'IgnoreImportLibrary', '', _boolean)
_Moved(_link, 'LinkIncremental', '', _newly_boolean)
_Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
_Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean)
# MSVS options not found in MSBuild.
_MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean)
_MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean)
# MSBuild options not found in MSVS.
_MSBuildOnly(_link, 'BuildingInIDE', _boolean)
_MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH
_MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false'
_MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS
_MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND
_MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND
_MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name)
_MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false'
_MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN
_MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION
_MSBuildOnly(_link, 'ForceFileOutput',
_Enumeration([], new=['Enabled', # /FORCE
# /FORCE:MULTIPLE
'MultiplyDefinedSymbolOnly',
'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED
_MSBuildOnly(_link, 'CreateHotPatchableImage',
_Enumeration([], new=['Enabled', # /FUNCTIONPADMIN
'X86Image', # /FUNCTIONPADMIN:5
'X64Image', # /FUNCTIONPADMIN:6
'ItaniumImage'])) # /FUNCTIONPADMIN:16
_MSBuildOnly(_link, 'CLRSupportLastError',
_Enumeration([], new=['Enabled', # /CLRSupportLastError
'Disabled', # /CLRSupportLastError:NO
# /CLRSupportLastError:SYSTEMDLL
'SystemDlls']))
'''
SwitchConverter.__init__(self, table, booltable)
CLSWITCHES = ClSwitchConverter()
LINKSWITCHES = LinkSwitchConverter()
#-------------------------------------------------------------------------------
# Return a Windows path from a native path
def winpath(path):
drive, rest = ntpath.splitdrive(path)
result = []
while rest and rest != ntpath.sep:
rest, part = ntpath.split(rest)
result.insert(0, part)
if rest:
result.insert(0, rest)
return ntpath.join(drive.upper(), *result)
def makeList(x):
if not x:
return []
if type(x) is not list:
return [x]
return x
#-------------------------------------------------------------------------------
class Configuration(object):
def __init__(self, variant, platform, target, env):
self.name = '%s|%s' % (variant, platform)
self.variant = variant
self.platform = platform
self.target = target
self.env = env
#-------------------------------------------------------------------------------
class Item(object):
'''Represents a file item in the Solution Explorer'''
def __init__(self, path, builder):
self._path = path
self._builder = builder
self.node = dict()
if builder == 'Object':
self._tag = 'ClCompile'
self._excluded = False
elif builder == 'Protoc':
self._tag = 'CustomBuild'
self._excluded = False
else:
ext = os.path.splitext(self._path)[1]
if ext in ['.c', '.cc', '.cpp']:
self._tag = 'ClCompile'
self._excluded = True
else:
if ext in ['.h', '.hpp', '.hxx', '.inl', '.inc']:
self._tag = 'ClInclude'
else:
self._tag = 'None'
self._excluded = False;
def __repr__(self):
return '<VSProject.Item "%s" %s>' % (
self.path, self.tag, str(self.node))
def path(self):
return self._path
def tag(self):
return self._tag
def builder(self):
return self._builder
def is_compiled(self):
return self._builder == 'Object'
def is_excluded(self):
return self._excluded
#-------------------------------------------------------------------------------
def _guid(seed, name = None):
m = hashlib.md5()
m.update(seed)
if name:
m.update(name)
d = m.hexdigest().upper()
guid = "{%s-%s-%s-%s-%s}" % (d[:8], d[8:12], d[12:16], d[16:20], d[20:32])
return guid
class _ProjectGenerator(object):
'''Generates a project file for Visual Studio 2013'''
def __init__(self, project_node, filters_node, env):
try:
self.configs = xsorted(env['VSPROJECT_CONFIGS'])
except KeyError:
raise ValueError ('Missing VSPROJECT_CONFIGS')
self.root_dir = os.getcwd()
self.root_dirs = [os.path.abspath(x) for x in makeList(env['VSPROJECT_ROOT_DIRS'])]
self.project_dir = os.path.dirname(os.path.abspath(str(project_node)))
self.project_node = project_node
self.project_file = None
self.filters_node = filters_node
self.filters_file = None
self.guid = _guid(os.path.basename(str(self.project_node)))
self.buildItemList(env)
def buildItemList(self, env):
'''Build the Item set associated with the configurations'''
items = {}
def _walk(target, items, prefix=''):
if os.path.isabs(str(target)):
return
if target.has_builder():
builder = target.get_builder().get_name(env)
bsources = target.get_binfo().bsources
if builder == 'Program':
for child in bsources:
_walk(child, items, prefix+' ')
else:
for child in bsources:
item = items.setdefault(str(child), Item(str(child), builder=builder))
item.node[config] = target
_walk(child, items, prefix+' ')
for child in target.children(scan=1):
if not os.path.isabs(str(child)):
item = items.setdefault(str(child), Item(str(child), builder=None))
_walk(child, items, prefix+' ')
for config in self.configs:
targets = config.target
for target in targets:
_walk(target, items)
self.items = xsorted(items.values())
def makeListTag(self, items, prefix, tag, attrs, inherit=True):
'''Builds an XML tag string from a list of items. If items is
empty, then the returned string is empty.'''
if not items:
return ''
s = '%(prefix)s<%(tag)s%(attrs)s>' % locals()
s += ';'.join(items)
if inherit:
s += ';%%(%(tag)s)' % locals()
s += '</%(tag)s>\r\n' % locals()
return s
def relPaths(self, paths):
items = []
for path in paths:
if not os.path.isabs(path):
items.append(winpath(os.path.relpath(path, self.project_dir)))
return items
def extraRelPaths(self, paths, base):
extras = []
for path in paths:
if not path in base:
extras.append(path)
return self.relPaths(extras)
def writeHeader(self):
global clSwitches
encoding = 'utf-8'
project_guid = self.guid
name = os.path.splitext(os.path.basename(str(self.project_node)))[0]
f = self.project_file
f.write(UnicodeByteMarker)
f.write(V14DSPHeader % locals())
f.write(V14DSPGlobals % locals())
f.write(' <ItemGroup Label="ProjectConfigurations">\r\n')
for config in self.configs:
variant = config.variant
platform = config.platform
f.write(V14DSPProjectConfiguration % locals())
f.write(' </ItemGroup>\r\n')
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r\n')
for config in self.configs:
variant = config.variant
platform = config.platform
use_debug_libs = variant == 'Debug'
variant_dir = os.path.relpath(os.path.dirname(
config.target[0].get_abspath()), self.project_dir)
out_dir = winpath(variant_dir) + ntpath.sep
int_dir = winpath(ntpath.join(variant_dir, 'src')) + ntpath.sep
f.write(V14DSPPropertyGroup % locals())
f.write(' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r\n')
f.write(' <ImportGroup Label="ExtensionSettings" />\r\n')
for config in self.configs:
variant = config.variant
platform = config.platform
f.write(V14DSPImportGroup % locals())
f.write(' <PropertyGroup Label="UserMacros" />\r\n')
for config in self.configs:
variant = config.variant
platform = config.platform
f.write(V14DSPItemDefinitionGroup % locals())
# Cl options
f.write(' <ClCompile>\r\n')
f.write(
' <PreprocessorDefinitions>%s%%(PreprocessorDefinitions)</PreprocessorDefinitions>\r\n' % (
itemList(config.env['CPPDEFINES'], ';')))
props = ''
props += self.makeListTag(self.relPaths(xsorted(config.env['CPPPATH'])),
' ', 'AdditionalIncludeDirectories', '', True)
f.write(props)
f.write(CLSWITCHES.getXml(xsorted(config.env['CCFLAGS']), ' '))
f.write(' </ClCompile>\r\n')
f.write(' <Link>\r\n')
props = ''
props += self.makeListTag(xsorted(config.env['LIBS']),
' ', 'AdditionalDependencies', '', True)
try:
props += self.makeListTag(self.relPaths(xsorted(config.env['LIBPATH'])),
' ', 'AdditionalLibraryDirectories', '', True)
except:
pass
f.write(props)
f.write(LINKSWITCHES.getXml(xsorted(config.env['LINKFLAGS']), ' '))
f.write(' </Link>\r\n')
f.write(' </ItemDefinitionGroup>\r\n')
def writeProject(self):
self.writeHeader()
f = self.project_file
self.project_file.write(' <ItemGroup>\r\n')
for item in self.items:
path = winpath(os.path.relpath(item.path(), self.project_dir))
tag = item.tag()
props = ''
if item.builder() == 'Object':
props = ''
for config in self.configs:
name = config.name
variant = config.variant
platform = config.platform
if not config in item.node:
props += \
''' <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'">True</ExcludedFromBuild>\r\n''' % locals()
for config, output in xsorted(item.node.items()):
name = config.name
env = output.get_build_env()
variant = config.variant
platform = config.platform
props += self.makeListTag(self.extraRelPaths(xsorted(env['CPPPATH']), config.env['CPPPATH']),
' ', 'AdditionalIncludeDirectories',
''' Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'"''' % locals(),
True)
elif item.is_excluded():
props = ' <ExcludedFromBuild>True</ExcludedFromBuild>\r\n'
elif item.builder() == 'Protoc':
for config, output in xsorted(item.node.items()):
name = config.name
out_dir = os.path.relpath(os.path.dirname(str(output)), self.project_dir)
cpp_out = winpath(out_dir)
out_parts = out_dir.split(os.sep)
out_parts.append(os.path.splitext(os.path.basename(item.path()))[0])
base_out = ntpath.join(*out_parts)
props += V14CustomBuildProtoc % locals()
f.write(' <%(tag)s Include="%(path)s">\r\n' % locals())
f.write(props)
f.write(' </%(tag)s>\r\n' % locals())
f.write(' </ItemGroup>\r\n')
f.write(
' <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r\n'
' <ImportGroup Label="ExtensionTargets">\r\n'
' </ImportGroup>\r\n'
'</Project>\r\n')
def writeFilters(self):
def getGroup(abspath):
abspath = os.path.dirname(abspath)
for d in self.root_dirs:
common = os.path.commonprefix([abspath, d])
if common == d:
return winpath(os.path.relpath(abspath, common))
return winpath(os.path.split(abspath)[1])
f = self.filters_file
f.write(UnicodeByteMarker)
f.write(V14DSPFiltersHeader)
f.write(' <ItemGroup>\r\n')
groups = set()
for item in self.items:
group = getGroup(os.path.abspath(item.path()))
while group != '':
groups.add(group)
group = ntpath.split(group)[0]
for group in xsorted(groups):
guid = _guid(self.guid, group)
f.write(
' <Filter Include="%(group)s">\r\n'
' <UniqueIdentifier>%(guid)s</UniqueIdentifier>\r\n'
' </Filter>\r\n' % locals())
f.write(' </ItemGroup>\r\n')
f.write(' <ItemGroup>\r\n')
for item in self.items:
path = os.path.abspath(item.path())
group = getGroup(path)
path = winpath(os.path.relpath(path, self.project_dir))
tag = item.tag()
f.write (
' <%(tag)s Include="%(path)s">\r\n'
' <Filter>%(group)s</Filter>\r\n'
' </%(tag)s>\r\n' % locals())
f.write(' </ItemGroup>\r\n')
f.write('</Project>\r\n')
def build(self):
try:
self.project_file = open(str(self.project_node), 'wb')
except IOError, detail:
raise SCons.Errors.InternalError('Unable to open "' +
str(self.project_node) + '" for writing:' + str(detail))
try:
self.filters_file = open(str(self.filters_node), 'wb')
except IOError, detail:
raise SCons.Errors.InternalError('Unable to open "' +
str(self.filters_node) + '" for writing:' + str(detail))
self.writeProject()
self.writeFilters()
self.project_file.close()
self.filters_file.close()
#-------------------------------------------------------------------------------
class _SolutionGenerator(object):
def __init__(self, slnfile, projfile, env):
pass
def build(self):
pass
#-------------------------------------------------------------------------------
# Generate the VS2013 project
def buildProject(target, source, env):
if env.get('auto_build_solution', 1):
if len(target) != 3:
raise ValueError ("Unexpected len(target) != 3")
if not env.get('auto_build_solution', 1):
if len(target) != 2:
raise ValueError ("Unexpected len(target) != 2")
g = _ProjectGenerator (target[0], target[1], env)
g.build()
if env.get('auto_build_solution', 1):
g = _SolutionGenerator (target[2], target[0], env)
g.build()
def projectEmitter(target, source, env):
if len(target) != 1:
raise ValueError ("Exactly one target must be specified")
# If source is unspecified this condition will be true
if not source or source[0] == target[0]:
source = []
outputs = []
for node in list(target):
path = env.GetBuildPath(node)
outputs.extend([
path + '.vcxproj',
path + '.vcxproj.filters'])
if env.get('auto_build_solution', 1):
outputs.append(path + '.sln')
return outputs, source
projectBuilder = SCons.Builder.Builder(
action = SCons.Action.Action(buildProject, "Building ${TARGET}"),
emitter = projectEmitter)
def createConfig(self, variant, platform, target, env):
return Configuration(variant, platform, target, env)
def generate(env):
'''Add Builders and construction variables for Microsoft Visual
Studio project files to an Environment.'''
try:
env['BUILDERS']['VSProject']
except KeyError:
env['BUILDERS']['VSProject'] = projectBuilder
env.AddMethod(createConfig, 'VSProjectConfig')
def exists(env):
return True

View File

@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2014, Howard Hinnant <howard.hinnant@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_TYPE_NAME_H_INCLUDED
#define BEAST_TYPE_NAME_H_INCLUDED
#include <type_traits>
#include <typeinfo>
#include <iostream>
#ifndef _MSC_VER
#include <cxxabi.h>
#endif
#include <memory>
#include <string>
#include <cstdlib>
#include <vector>
namespace beast {
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4127) // conditional expression is constant
#endif
template <typename T>
std::string
type_name()
{
using TR = typename std::remove_reference<T>::type;
std::unique_ptr<char, void(*)(void*)> own (
#ifndef _MSC_VER
abi::__cxa_demangle (typeid(TR).name(), nullptr,
nullptr, nullptr),
#else
nullptr,
#endif
std::free
);
std::string r = own != nullptr ? own.get() : typeid(TR).name();
if (std::is_const<TR>::value)
r += " const";
if (std::is_volatile<TR>::value)
r += " volatile";
if (std::is_lvalue_reference<T>::value)
r += "&";
else if (std::is_rvalue_reference<T>::value)
r += "&&";
return r;
}
#ifdef _MSC_VER
#pragma warning (pop)
#endif
} // beast
#endif

View File

@@ -0,0 +1,41 @@
//------------------------------------------------------------------------------
/*
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_UNIT_TEST_H_INCLUDED
#define BEAST_UNIT_TEST_H_INCLUDED
#include <beast/detail/unit_test/amount.hpp>
#include <beast/detail/unit_test/print.hpp>
#include <beast/detail/unit_test/global_suites.hpp>
#include <beast/detail/unit_test/match.hpp>
#include <beast/detail/unit_test/recorder.hpp>
#include <beast/detail/unit_test/reporter.hpp>
#include <beast/detail/unit_test/results.hpp>
#include <beast/detail/unit_test/runner.hpp>
#include <beast/detail/unit_test/suite.hpp>
#include <beast/detail/unit_test/suite_info.hpp>
#include <beast/detail/unit_test/suite_list.hpp>
namespace beast {
namespace unit_test {
using namespace beast::detail::unit_test;
} // unit_test
} // beast
#endif

View File

@@ -0,0 +1,21 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <ripple/beast/clock/tests/beast_abstract_clock_test.cpp>
#include <ripple/beast/clock/tests/beast_basic_seconds_clock_test.cpp>

View File

@@ -0,0 +1,29 @@
//------------------------------------------------------------------------------
/*
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.
*/
//==============================================================================
#include <ripple/beast/hash/xxhasher.h>
#include <ripple/beast/hash/impl/spookyv2.cpp>
#if ! BEAST_NO_XXHASH
#include <ripple/beast/hash/impl/xxhash.c>
#endif
#include <ripple/beast/hash/impl/siphash.cpp>
#include <ripple/beast/hash/tests/hash_append_test.cpp>
#include <ripple/beast/hash/tests/hash_speed_test.cpp>

View File

@@ -21,7 +21,5 @@
#include <ripple/beast/net/impl/IPAddressV6.cpp>
#include <ripple/beast/net/impl/IPEndpoint.cpp>
#include <ripple/beast/net/impl/IPAddressConversion.cpp>
#include <ripple/beast/net/impl/URL.cpp>
#include <ripple/beast/net/tests/beast_http_URL_test.cpp>
#include <ripple/beast/net/tests/IPEndpoint.test.cpp>

Some files were not shown because too many files have changed in this diff Show More