mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Reorganize source files
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -23,8 +23,4 @@ contents.xcworkspacedata
|
||||
.DS_Store
|
||||
.svn
|
||||
profile
|
||||
Builds/VisualStudio2012/Debug
|
||||
Builds/VisualStudio2012/Release
|
||||
project.xcworkspace
|
||||
modules/beast_cryptopp
|
||||
bin/
|
||||
|
||||
26
.travis.yml
26
.travis.yml
@@ -1,26 +0,0 @@
|
||||
language: cpp
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-software-properties
|
||||
- sudo apt-get install -qq g++-4.8
|
||||
- sudo apt-get install -qq libboost1.55-all-dev
|
||||
- sudo apt-get install -qq libssl-dev
|
||||
- sudo apt-get install -qq gcc-4.8
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
|
||||
- sudo update-alternatives --set gcc /usr/bin/gcc-4.8
|
||||
# - sudo apt-get -y install binutils-gold
|
||||
- g++ -v
|
||||
- clang -v
|
||||
script:
|
||||
# Abort build on failure
|
||||
- set -e
|
||||
- scons
|
||||
notifications:
|
||||
email:
|
||||
false
|
||||
139
BeastConfig.h
139
BeastConfig.h
@@ -1,139 +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_BEASTCONFIG_H_INCLUDED
|
||||
#define BEAST_BEASTCONFIG_H_INCLUDED
|
||||
|
||||
/** Configuration file for Beast.
|
||||
This sets various configurable options for Beast. In order to compile you
|
||||
must place a copy of this file in a location where your build environment
|
||||
can find it, and then customize its contents to suit your needs.
|
||||
@file BeastConfig.h
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Unit Tests
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_NO_UNIT_TEST_INLINE
|
||||
Prevents unit test definitions from being inserted into a global table.
|
||||
*/
|
||||
#ifndef BEAST_NO_UNIT_TEST_INLINE
|
||||
#define BEAST_NO_UNIT_TEST_INLINE 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Diagnostics
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_FORCE_DEBUG
|
||||
Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project
|
||||
settings, but if you define this value, you can override this to force it
|
||||
to be true or false.
|
||||
*/
|
||||
#ifndef BEAST_FORCE_DEBUG
|
||||
//#define BEAST_FORCE_DEBUG 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
Enables a memory-leak check for certain objects when the app terminates.
|
||||
See the LeakChecked class for more details about enabling leak checking for
|
||||
specific classes.
|
||||
*/
|
||||
#ifndef BEAST_CHECK_MEMORY_LEAKS
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Libraries
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
In a Visual C++ build, this can be used to stop the required system libs
|
||||
being automatically added to the link stage.
|
||||
*/
|
||||
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_INCLUDE_ZLIB_CODE
|
||||
This can be used to disable Beast's embedded 3rd-party zlib code.
|
||||
You might need to tweak this if you're linking to an external zlib library
|
||||
in your app, but for normal apps, this option should be left alone.
|
||||
|
||||
If you disable this, you might also want to set a value for
|
||||
BEAST_ZLIB_INCLUDE_PATH, to specify the path where your zlib headers live.
|
||||
*/
|
||||
#ifndef BEAST_INCLUDE_ZLIB_CODE
|
||||
//#define BEAST_INCLUDE_ZLIB_CODE 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_ZLIB_INCLUDE_PATH
|
||||
This is included when BEAST_INCLUDE_ZLIB_CODE is set to zero.
|
||||
*/
|
||||
#ifndef BEAST_ZLIB_INCLUDE_PATH
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_SQLITE_FORCE_NDEBUG
|
||||
Setting this option forces sqlite into release mode even if NDEBUG is not set
|
||||
*/
|
||||
#ifndef BEAST_SQLITE_FORCE_NDEBUG
|
||||
//#define BEAST_SQLITE_FORCE_NDEBUG 1
|
||||
#endif
|
||||
|
||||
/** Config: BEAST_FUNCTIONAL_USES_###
|
||||
<functional> source configuration.
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
If nothing is chosen then beast will use whatever is appropriate for your
|
||||
environment based on what is available.
|
||||
If you override these, set ONE to 1 and the rest to 0
|
||||
*/
|
||||
#ifndef BEAST_FUNCTIONAL_USES_STD
|
||||
//#define BEAST_FUNCTIONAL_USES_STD 0
|
||||
#endif
|
||||
#ifndef BEAST_FUNCTIONAL_USES_TR1
|
||||
//#define BEAST_FUNCTIONAL_USES_TR1 0
|
||||
#endif
|
||||
#ifndef BEAST_FUNCTIONAL_USES_BOOST
|
||||
//#define BEAST_FUNCTIONAL_USES_BOOST 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Boost
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_USE_BOOST_FEATURES
|
||||
This activates boost specific features and improvements. If this is
|
||||
turned on, the include paths for your build environment must be set
|
||||
correctly to find the boost headers.
|
||||
*/
|
||||
#ifndef BEAST_USE_BOOST_FEATURES
|
||||
//#define BEAST_USE_BOOST_FEATURES 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1
Jamroot
1
Jamroot
@@ -48,6 +48,7 @@ else
|
||||
project beast
|
||||
: requirements
|
||||
<include>.
|
||||
<include>./include
|
||||
#<use>/boost//headers
|
||||
<library>/boost/system//boost_system
|
||||
<library>/boost/filesystem//boost_filesystem
|
||||
|
||||
13
README.md
13
README.md
@@ -1 +1,12 @@
|
||||
# Beast: A C++ Library
|
||||
# Beast
|
||||
|
||||
Beast provides implementations of the HTTP and WebSocket protocols
|
||||
built on top of Boost.Asio and other parts of boost.
|
||||
|
||||
Requirements:
|
||||
|
||||
* Boost
|
||||
* C++11 or greater
|
||||
* OpenSSL (optional)
|
||||
|
||||
Documentation: http://vinniefalco.github.io/beast/
|
||||
|
||||
20
TODO.txt
20
TODO.txt
@@ -1,8 +1,22 @@
|
||||
* kick out non-beast code
|
||||
|
||||
* redo directory structure
|
||||
|
||||
* Change build options to C++11 only
|
||||
|
||||
* Replace Jamroot with Jamfile
|
||||
* Switch source material to Boost license
|
||||
* Fix failing test/message.cpp
|
||||
* Complete allocator testing in basic_streambuf, basic_headers
|
||||
* Tidy up type_checks
|
||||
- Derive from std::integral_constant
|
||||
* Check DOXYGEN, GENERATIC_DOCS directives in source
|
||||
- See if we can include them now that xsl is fixed
|
||||
* Go over each header and split header material into detail and impl files
|
||||
* Make buffers_debug a detail
|
||||
* Ensure each public header has a unit test .cpp file
|
||||
* Roll header-only http parser
|
||||
* Define Parser concept in HTTP
|
||||
* melpon sandbox?
|
||||
* invokable unit test
|
||||
* trim public interface of rfc2616.h to essentials only
|
||||
* Use new http routines in JSONRPCClient
|
||||
* Remove or change http::headers alias
|
||||
|
||||
|
||||
38
beast/asio.h
38
beast/asio.h
@@ -1,38 +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_ASIO_H_INCLUDED
|
||||
#define BEAST_ASIO_H_INCLUDED
|
||||
|
||||
#include <beast/asio/append_buffers.h>
|
||||
#include <beast/asio/async_completion.h>
|
||||
#include <beast/asio/basic_streambuf.h>
|
||||
#include <beast/asio/bind_handler.h>
|
||||
#include <beast/asio/buffers_adapter.h>
|
||||
#include <beast/asio/buffers_debug.h>
|
||||
#include <beast/asio/consuming_buffers.h>
|
||||
#include <beast/asio/handler_alloc.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <beast/asio/prepare_buffers.h>
|
||||
#include <beast/asio/static_streambuf.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/asio/streambuf_readstream.h>
|
||||
#include <beast/asio/type_check.h>
|
||||
|
||||
#endif
|
||||
@@ -1,51 +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_ASIO_BUFFERS_DEBUG_H_INLUDED
|
||||
#define BEAST_ASIO_BUFFERS_DEBUG_H_INLUDED
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace debug {
|
||||
|
||||
template<class Buffers>
|
||||
std::string
|
||||
buffers_to_string(Buffers const& bs)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string s;
|
||||
s.reserve(buffer_size(bs));
|
||||
for(auto const& b : bs)
|
||||
s.append(buffer_cast<char const*>(b),
|
||||
buffer_size(b));
|
||||
for(auto i = s.size(); i-- > 0;)
|
||||
if(s[i] == '\r')
|
||||
s.replace(i, 1, "\\r");
|
||||
else if(s[i] == '\n')
|
||||
s.replace(i, 1, "\\n\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
} // debug
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,244 +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_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
|
||||
@@ -1,41 +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_ASIO_PLACEHOLDERS_H_INCLUDED
|
||||
#define BEAST_ASIO_PLACEHOLDERS_H_INCLUDED
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
namespace placeholders {
|
||||
// asio placeholders that work with std::bind
|
||||
namespace {
|
||||
static auto const error (std::placeholders::_1);
|
||||
static auto const bytes_transferred (std::placeholders::_2);
|
||||
static auto const iterator (std::placeholders::_2);
|
||||
static auto const signal_number (std::placeholders::_2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,48 +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 <beast/unit_test/suite.h>
|
||||
#include <beast/asio/bind_handler.h>
|
||||
#include <functional>
|
||||
|
||||
namespace beast {
|
||||
namespace test {
|
||||
|
||||
class bind_handler_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
static void foo (int)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
auto f (bind_handler (
|
||||
std::bind (&foo, std::placeholders::_1),
|
||||
42));
|
||||
f();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(bind_handler,asio,beast);
|
||||
|
||||
} // test
|
||||
} // beast
|
||||
|
||||
@@ -1,362 +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 <beast/asio/append_buffers.h>
|
||||
#include <beast/asio/buffers_adapter.h>
|
||||
#include <beast/asio/prepare_buffers.h>
|
||||
#include <beast/asio/consuming_buffers.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/asio/static_streambuf.h>
|
||||
#include <beast/asio/streambuf_readstream.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace test {
|
||||
|
||||
class buffers_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class ConstBufferSequence>
|
||||
static
|
||||
std::string
|
||||
to_string(ConstBufferSequence const& bs)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string s;
|
||||
s.reserve(buffer_size(bs));
|
||||
for(auto const& b : bs)
|
||||
s.append(buffer_cast<char const*>(b),
|
||||
buffer_size(b));
|
||||
return s;
|
||||
}
|
||||
|
||||
void testStreambuf()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == 12);
|
||||
for(std::size_t i = 1; i < 12; ++i) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
for(std::size_t t = 1; t < 4; ++ t) {
|
||||
for(std::size_t u = 1; u < 4; ++ u) {
|
||||
std::size_t z = s.size() - (x + y);
|
||||
std::size_t v = s.size() - (t + u);
|
||||
{
|
||||
streambuf sb(i);
|
||||
decltype(sb)::mutable_buffers_type d;
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
sb.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(sb.size() == x);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
sb.commit(1);
|
||||
expect(sb.size() == x + y);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
d = sb.prepare(x); expect(buffer_size(d) == x);
|
||||
d = sb.prepare(y); expect(buffer_size(d) == y);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = sb.prepare(z); expect(buffer_size(d) == z);
|
||||
sb.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
sb.commit(2);
|
||||
expect(sb.size() == x + y + z);
|
||||
expect(buffer_size(sb.data()) == sb.size());
|
||||
expect(to_string(sb.data()) == s);
|
||||
sb.consume(t);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(sb.data()) == s.substr(t, std::string::npos));
|
||||
sb.consume(u);
|
||||
expect(to_string(sb.data()) == s.substr(t + u, std::string::npos));
|
||||
sb.consume(v);
|
||||
expect(to_string(sb.data()) == "");
|
||||
sb.consume(1);
|
||||
d = sb.prepare(0); expect(buffer_size(d) == 0);
|
||||
}
|
||||
}}}}}
|
||||
}
|
||||
|
||||
void testBuffersAdapter()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
using boost::asio::mutable_buffer;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == sizeof(buf));
|
||||
for(std::size_t i = 1; i < 4; ++i) {
|
||||
for(std::size_t j = 1; j < 4; ++j) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
for(std::size_t t = 1; t < 4; ++ t) {
|
||||
for(std::size_t u = 1; u < 4; ++ u) {
|
||||
std::size_t k = sizeof(buf) - (i + j);
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
std::size_t v = sizeof(buf) - (t + u);
|
||||
{
|
||||
std::memset(buf, 0, sizeof(buf));
|
||||
std::array<mutable_buffer, 3> bs{{
|
||||
mutable_buffer{&buf[0], i},
|
||||
mutable_buffer{&buf[i], j},
|
||||
mutable_buffer{&buf[i+j], k}}};
|
||||
buffers_adapter<decltype(bs)> ba(std::move(bs));
|
||||
expect(ba.max_size() == sizeof(buf));
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(ba.size() == x);
|
||||
expect(ba.max_size() == sizeof(buf) - x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(ba.max_size() == sizeof(buf) - (x + y));
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(ba.max_size() == 0);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
fail();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}}}}}}
|
||||
}
|
||||
|
||||
void testConsuming()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::const_buffer;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == sizeof(buf));
|
||||
buffer_copy(buffer(buf), buffer(s));
|
||||
expect(to_string(buffer(buf)) == s);
|
||||
for(std::size_t i = 1; i < 4; ++i) {
|
||||
for(std::size_t j = 1; j < 4; ++j) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
std::size_t k = sizeof(buf) - (i + j);
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
{
|
||||
std::array<const_buffer, 3> bs{{
|
||||
const_buffer{&buf[0], i},
|
||||
const_buffer{&buf[i], j},
|
||||
const_buffer{&buf[i+j], k}}};
|
||||
consuming_buffers<decltype(bs)> cb(bs);
|
||||
expect(to_string(cb) == s);
|
||||
cb.consume(0);
|
||||
expect(to_string(cb) == s);
|
||||
cb.consume(x);
|
||||
expect(to_string(cb) == s.substr(x));
|
||||
cb.consume(y);
|
||||
expect(to_string(cb) == s.substr(x+y));
|
||||
cb.consume(z);
|
||||
expect(to_string(cb) == "");
|
||||
cb.consume(1);
|
||||
expect(to_string(cb) == "");
|
||||
}
|
||||
}}}}
|
||||
}
|
||||
|
||||
void testStaticBuffers()
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
char buf[12];
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == sizeof(buf));
|
||||
for(std::size_t i = 1; i < 4; ++i) {
|
||||
for(std::size_t j = 1; j < 4; ++j) {
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
for(std::size_t t = 1; t < 4; ++ t) {
|
||||
for(std::size_t u = 1; u < 4; ++ u) {
|
||||
std::size_t z = sizeof(buf) - (x + y);
|
||||
std::size_t v = sizeof(buf) - (t + u);
|
||||
{
|
||||
std::memset(buf, 0, sizeof(buf));
|
||||
static_streambuf_n<sizeof(buf)> ba;
|
||||
decltype(ba)::mutable_buffers_type d;
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
ba.commit(buffer_copy(d, buffer(s.data(), x)));
|
||||
expect(ba.size() == x);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x, y)));
|
||||
ba.commit(1);
|
||||
expect(ba.size() == x + y);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
d = ba.prepare(x); expect(buffer_size(d) == x);
|
||||
d = ba.prepare(y); expect(buffer_size(d) == y);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
d = ba.prepare(z); expect(buffer_size(d) == z);
|
||||
ba.commit(buffer_copy(d, buffer(s.data()+x+y, z)));
|
||||
ba.commit(2);
|
||||
expect(ba.size() == x + y + z);
|
||||
expect(buffer_size(ba.data()) == ba.size());
|
||||
expect(to_string(ba.data()) == s);
|
||||
ba.consume(t);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
expect(to_string(ba.data()) == s.substr(t, std::string::npos));
|
||||
ba.consume(u);
|
||||
expect(to_string(ba.data()) == s.substr(t + u, std::string::npos));
|
||||
ba.consume(v);
|
||||
expect(to_string(ba.data()) == "");
|
||||
ba.consume(1);
|
||||
d = ba.prepare(0); expect(buffer_size(d) == 0);
|
||||
try
|
||||
{
|
||||
ba.prepare(1);
|
||||
fail();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
pass();
|
||||
}
|
||||
}
|
||||
}}}}}}
|
||||
}
|
||||
|
||||
void testAppendBuffers()
|
||||
{
|
||||
using boost::asio::buffer_size;
|
||||
using boost::asio::const_buffer;
|
||||
char buf[10];
|
||||
std::list<const_buffer> b1;
|
||||
std::vector<const_buffer> b2{
|
||||
const_buffer{buf+0, 1},
|
||||
const_buffer{buf+1, 2}};
|
||||
std::list<const_buffer> b3;
|
||||
std::array<const_buffer, 3> b4{{
|
||||
const_buffer{buf+3, 1},
|
||||
const_buffer{buf+4, 2},
|
||||
const_buffer{buf+6, 3}}};
|
||||
std::list<const_buffer> b5{
|
||||
const_buffer{buf+9, 1}};
|
||||
std::list<const_buffer> b6;
|
||||
auto bs = append_buffers(
|
||||
b1, b2, b3, b4, b5, b6);
|
||||
expect(buffer_size(bs) == 10);
|
||||
std::vector<const_buffer> v;
|
||||
for(auto iter = std::make_reverse_iterator(bs.end());
|
||||
iter != std::make_reverse_iterator(bs.begin()); ++iter)
|
||||
v.emplace_back(*iter);
|
||||
expect(buffer_size(bs) == 10);
|
||||
decltype(bs) bs2(bs);
|
||||
auto bs3(std::move(bs));
|
||||
bs = bs2;
|
||||
bs3 = std::move(bs2);
|
||||
{
|
||||
streambuf sb1, sb2;
|
||||
expect(buffer_size(append_buffers(
|
||||
sb1.prepare(5), sb2.prepare(7))) == 12);
|
||||
sb1.commit(5);
|
||||
sb2.commit(7);
|
||||
expect(buffer_size(append_buffers(
|
||||
sb1.data(), sb2.data())) == 12);
|
||||
}
|
||||
}
|
||||
|
||||
void testClipBuffers()
|
||||
{
|
||||
using boost::asio::const_buffer;
|
||||
std::string const s = "Hello, world";
|
||||
expect(s.size() == 12);
|
||||
for(std::size_t x = 1; x < 4; ++x) {
|
||||
for(std::size_t y = 1; y < 4; ++y) {
|
||||
std::size_t z = s.size() - (x + y);
|
||||
{
|
||||
std::array<const_buffer, 3> bs{{
|
||||
const_buffer{&s[0], x},
|
||||
const_buffer{&s[x], y},
|
||||
const_buffer{&s[x+y], z}}};
|
||||
for(std::size_t i = 0; i <= s.size() + 1; ++i)
|
||||
expect(to_string(prepare_buffers(i, bs)) ==
|
||||
s.substr(0, i));
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testStreambuf();
|
||||
testBuffersAdapter();
|
||||
testConsuming();
|
||||
testStaticBuffers();
|
||||
|
||||
testAppendBuffers();
|
||||
testClipBuffers();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(buffers,asio,beast);
|
||||
|
||||
} // test
|
||||
} // beast
|
||||
@@ -1,43 +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 <beast/asio/ssl_error.h>
|
||||
#include <beast/unit_test/suite.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
|
||||
@@ -1,71 +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_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
|
||||
@@ -1,72 +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_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
|
||||
@@ -1,31 +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_ASIO_STREAMBUF_H_INCLUDED
|
||||
#define BEAST_ASIO_STREAMBUF_H_INCLUDED
|
||||
|
||||
#include <beast/asio/basic_streambuf.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
using streambuf = basic_streambuf<std::allocator<char>>;
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,109 +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_ASIO_TEMP_BUFFER_H_INCLUDED
|
||||
#define BEAST_ASIO_TEMP_BUFFER_H_INCLUDED
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/detail/handler_alloc_helpers.hpp>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
template<class Handler>
|
||||
class temp_buffer
|
||||
{
|
||||
Handler& h_;
|
||||
std::size_t n_ = 0;
|
||||
std::uint8_t* p_ = nullptr;
|
||||
|
||||
public:
|
||||
explicit
|
||||
temp_buffer(Handler& h)
|
||||
: h_(h)
|
||||
{
|
||||
}
|
||||
|
||||
~temp_buffer()
|
||||
{
|
||||
if(p_)
|
||||
dealloc();
|
||||
}
|
||||
|
||||
operator
|
||||
boost::asio::const_buffer() const
|
||||
{
|
||||
return boost::asio::const_buffer{p_, n_};
|
||||
}
|
||||
|
||||
operator
|
||||
boost::asio::mutable_buffer() const
|
||||
{
|
||||
return boost::asio::mutable_buffer{p_, n_};
|
||||
}
|
||||
|
||||
std::uint8_t*
|
||||
data() const
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size()
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
boost::asio::mutable_buffers_1
|
||||
buffers() const
|
||||
{
|
||||
return boost::asio::mutable_buffers_1{
|
||||
p_, n_};
|
||||
}
|
||||
|
||||
void
|
||||
alloc(std::size_t size)
|
||||
{
|
||||
if(n_ != size)
|
||||
{
|
||||
if(p_)
|
||||
dealloc();
|
||||
n_ = size;
|
||||
if(n_ > 0)
|
||||
p_ = reinterpret_cast<std::uint8_t*>(
|
||||
boost_asio_handler_alloc_helpers::
|
||||
allocate(n_, h_));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dealloc()
|
||||
{
|
||||
boost_asio_handler_alloc_helpers::
|
||||
deallocate(p_, n_, h_);
|
||||
p_ = nullptr;
|
||||
n_ = 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,111 +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_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
|
||||
@@ -1,217 +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_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED
|
||||
#define BEAST_CHRONO_BASIC_SECONDS_CLOCK_H_INCLUDED
|
||||
|
||||
#include <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
|
||||
@@ -1,68 +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_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
|
||||
@@ -1,100 +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_CHRONO_MANUAL_CLOCK_H_INCLUDED
|
||||
#define BEAST_CHRONO_MANUAL_CLOCK_H_INCLUDED
|
||||
|
||||
#include <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
|
||||
@@ -1,93 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// MODULES: ../impl/chrono_io.cpp
|
||||
|
||||
#include <beast/clock/abstract_clock.h>
|
||||
#include <beast/clock/manual_clock.h>
|
||||
#include <beast/unit_test/suite.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);
|
||||
|
||||
}
|
||||
@@ -1,40 +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 <beast/unit_test/suite.h>
|
||||
|
||||
#include <beast/clock/basic_seconds_clock.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class basic_seconds_clock_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
run()
|
||||
{
|
||||
basic_seconds_clock <
|
||||
std::chrono::steady_clock>::now ();
|
||||
pass ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_seconds_clock,chrono,beast);
|
||||
|
||||
}
|
||||
@@ -1,92 +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_CRYPTO_MAC_FACADE_H_INCLUDED
|
||||
#define BEAST_CRYPTO_MAC_FACADE_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/secure_erase.h>
|
||||
#include <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
|
||||
@@ -1,429 +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_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
|
||||
@@ -1,428 +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_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
|
||||
@@ -1,37 +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_CRYPTO_RIPEMD_H_INCLUDED
|
||||
#define BEAST_CRYPTO_RIPEMD_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/detail/mac_facade.h>
|
||||
#include <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
|
||||
@@ -1,87 +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_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
|
||||
@@ -1,34 +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_CRYPTO_SHA_H_INCLUDED
|
||||
#define BEAST_CRYPTO_SHA_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/detail/mac_facade.h>
|
||||
#include <beast/crypto/detail/sha_context.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
// non-secure
|
||||
using sha_hasher = detail::mac_facade<
|
||||
detail::sha_context, false>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,44 +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_CRYPTO_SHA2_H_INCLUDED
|
||||
#define BEAST_CRYPTO_SHA2_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/detail/mac_facade.h>
|
||||
#include <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
|
||||
@@ -1,56 +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_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
|
||||
@@ -1,111 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_EMPTY_BASE_OPTIMIZATION_H_INCLUDED
|
||||
#define BEAST_EMPTY_BASE_OPTIMIZATION_H_INCLUDED
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct empty_base_optimization_decide
|
||||
: std::integral_constant <bool,
|
||||
std::is_empty <T>::value
|
||||
#ifdef __clang__
|
||||
&& !__is_final(T)
|
||||
#endif
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
class T,
|
||||
int UniqueID = 0,
|
||||
bool ShouldDeriveFrom =
|
||||
detail::empty_base_optimization_decide <T>::value
|
||||
>
|
||||
class empty_base_optimization : private T
|
||||
{
|
||||
public:
|
||||
empty_base_optimization() = default;
|
||||
|
||||
empty_base_optimization(T const& t)
|
||||
: T (t)
|
||||
{}
|
||||
|
||||
empty_base_optimization(T&& t)
|
||||
: T (std::move (t))
|
||||
{}
|
||||
|
||||
T& member() noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
T const& member() const noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
class T,
|
||||
int UniqueID
|
||||
>
|
||||
class empty_base_optimization <T, UniqueID, false>
|
||||
{
|
||||
public:
|
||||
empty_base_optimization() = default;
|
||||
|
||||
empty_base_optimization(T const& t)
|
||||
: m_t (t)
|
||||
{}
|
||||
|
||||
empty_base_optimization(T&& t)
|
||||
: m_t (std::move (t))
|
||||
{}
|
||||
|
||||
T& member() noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
|
||||
T const& member() const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,70 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,516 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <beast/hash/endian.h>
|
||||
#include <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
|
||||
@@ -1,85 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#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
|
||||
@@ -1,165 +0,0 @@
|
||||
//------------------------------- 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 <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
|
||||
@@ -1,361 +0,0 @@
|
||||
// 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 <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
|
||||
@@ -1,301 +0,0 @@
|
||||
//
|
||||
// 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
|
||||
@@ -1,934 +0,0 @@
|
||||
/*
|
||||
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 <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
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
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
|
||||
@@ -1,140 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,60 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,61 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <beast/hash/endian.h>
|
||||
#include <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
|
||||
@@ -1,490 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include <BeastConfig.h>
|
||||
#endif
|
||||
|
||||
#include <beast/hash/endian.h>
|
||||
#include <beast/hash/tests/hash_metrics.h>
|
||||
#include <beast/hash/hash_append.h>
|
||||
#include <beast/xor_shift_engine.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <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);
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,119 +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 <beast/hash/fnv1a.h>
|
||||
#include <beast/hash/siphash.h>
|
||||
#include <beast/hash/xxhasher.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:
|
||||
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
|
||||
@@ -1,47 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <beast/hash/hash_append.h>
|
||||
#include <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
|
||||
@@ -1,88 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <beast/hash/endian.h>
|
||||
#include <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
|
||||
39
beast/http.h
39
beast/http.h
@@ -1,39 +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_H_INCLUDED
|
||||
#define BEAST_HTTP_H_INCLUDED
|
||||
|
||||
#include <beast/http/basic_parser.h>
|
||||
#include <beast/http/chunk_encode.h>
|
||||
#include <beast/http/empty_body.h>
|
||||
#include <beast/http/error.h>
|
||||
#include <beast/http/fields.h>
|
||||
#include <beast/http/headers.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/parser.h>
|
||||
#include <beast/http/read.h>
|
||||
#include <beast/http/reason.h>
|
||||
#include <beast/http/resume_context.h>
|
||||
#include <beast/http/streambuf_body.h>
|
||||
#include <beast/http/string_body.h>
|
||||
#include <beast/http/type_check.h>
|
||||
#include <beast/http/write.h>
|
||||
|
||||
#endif
|
||||
@@ -1,150 +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_BODY_H_INCLUDED
|
||||
#define BEAST_HTTP_BODY_H_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
} // deprecated_http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,87 +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_EMPTY_BODY_H_INCLUDED
|
||||
#define BEAST_HTTP_EMPTY_BODY_H_INCLUDED
|
||||
|
||||
#include <beast/http/error.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** An empty content-body.
|
||||
*/
|
||||
struct empty_body
|
||||
{
|
||||
struct value_type
|
||||
{
|
||||
};
|
||||
|
||||
struct reader
|
||||
{
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
reader(message<isRequest, empty_body, Allocator>&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
write(void const*, std::size_t, error_code&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct writer
|
||||
{
|
||||
template<bool isRequest, class Allocator>
|
||||
explicit
|
||||
writer(message<isRequest, empty_body, Allocator> const& m)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t
|
||||
content_length() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class Write>
|
||||
boost::tribool
|
||||
operator()(resume_context&&, error_code&, Write&& write)
|
||||
{
|
||||
write(boost::asio::null_buffers{});
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,38 +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_HEADERS_H_INCLUDED
|
||||
#define BEAST_HTTP_HEADERS_H_INCLUDED
|
||||
|
||||
#include <beast/http/basic_headers.h>
|
||||
#include <memory>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<class Allocator>
|
||||
using headers = basic_headers<Allocator>;
|
||||
|
||||
using http_headers =
|
||||
basic_headers<std::allocator<char>>;
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
git-subtree: "http-parser"
|
||||
remote: https://github.com/joyent/http-parser.git
|
||||
branch: master
|
||||
30
beast/http/impl/http-parser/.gitignore
vendored
30
beast/http/impl/http-parser/.gitignore
vendored
@@ -1,30 +0,0 @@
|
||||
/out/
|
||||
core
|
||||
tags
|
||||
*.o
|
||||
test
|
||||
test_g
|
||||
test_fast
|
||||
bench
|
||||
url_parser
|
||||
parsertrace
|
||||
parsertrace_g
|
||||
*.mk
|
||||
*.Makefile
|
||||
*.so.*
|
||||
*.exe.*
|
||||
*.exe
|
||||
*.a
|
||||
|
||||
|
||||
# Visual Studio uglies
|
||||
*.suo
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
*.opensdf
|
||||
*.ncrunchsolution*
|
||||
*.sdf
|
||||
*.vsp
|
||||
*.psess
|
||||
@@ -1,8 +0,0 @@
|
||||
# update AUTHORS with:
|
||||
# git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS
|
||||
Ryan Dahl <ry@tinyclouds.org>
|
||||
Salman Haq <salman.haq@asti-usa.com>
|
||||
Simon Zimmermann <simonz05@gmail.com>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>
|
||||
Fedor Indutny <fedor@indutny.com>
|
||||
@@ -1,13 +0,0 @@
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
script:
|
||||
- "make"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
- "irc.freenode.net#node-ci"
|
||||
@@ -1,149 +0,0 @@
|
||||
# Copyright Joyent, Inc. and other Node contributors. 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.
|
||||
|
||||
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
||||
HELPER ?=
|
||||
BINEXT ?=
|
||||
ifeq (darwin,$(PLATFORM))
|
||||
SONAME ?= libhttp_parser.2.6.1.dylib
|
||||
SOEXT ?= dylib
|
||||
else ifeq (wine,$(PLATFORM))
|
||||
CC = winegcc
|
||||
BINEXT = .exe.so
|
||||
HELPER = wine
|
||||
else
|
||||
SONAME ?= libhttp_parser.so.2.6.1
|
||||
SOEXT ?= so
|
||||
endif
|
||||
|
||||
CC?=gcc
|
||||
AR?=ar
|
||||
|
||||
CPPFLAGS ?=
|
||||
LDFLAGS ?=
|
||||
|
||||
CPPFLAGS += -I.
|
||||
CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1
|
||||
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
|
||||
CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0
|
||||
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
|
||||
CPPFLAGS_BENCH = $(CPPFLAGS_FAST)
|
||||
|
||||
CFLAGS += -Wall -Wextra -Werror
|
||||
CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
|
||||
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
|
||||
CFLAGS_BENCH = $(CFLAGS_FAST) -Wno-unused-parameter
|
||||
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
||||
|
||||
LDFLAGS_LIB = $(LDFLAGS) -shared
|
||||
|
||||
INSTALL ?= install
|
||||
PREFIX ?= $(DESTDIR)/usr/local
|
||||
LIBDIR = $(PREFIX)/lib
|
||||
INCLUDEDIR = $(PREFIX)/include
|
||||
|
||||
ifneq (darwin,$(PLATFORM))
|
||||
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
||||
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
||||
endif
|
||||
|
||||
test: test_g test_fast
|
||||
$(HELPER) ./test_g$(BINEXT)
|
||||
$(HELPER) ./test_fast$(BINEXT)
|
||||
|
||||
test_g: http_parser_g.o test_g.o
|
||||
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
|
||||
|
||||
test_g.o: test.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@
|
||||
|
||||
http_parser_g.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@
|
||||
|
||||
test_fast: http_parser.o test.o http_parser.h
|
||||
$(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@
|
||||
|
||||
test.o: test.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
|
||||
|
||||
bench: http_parser.o bench.o
|
||||
$(CC) $(CFLAGS_BENCH) $(LDFLAGS) http_parser.o bench.o -o $@
|
||||
|
||||
bench.o: bench.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_BENCH) $(CFLAGS_BENCH) -c bench.c -o $@
|
||||
|
||||
http_parser.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
|
||||
|
||||
test-run-timed: test_fast
|
||||
while(true) do time $(HELPER) ./test_fast$(BINEXT) > /dev/null; done
|
||||
|
||||
test-valgrind: test_g
|
||||
valgrind ./test_g
|
||||
|
||||
libhttp_parser.o: http_parser.c http_parser.h Makefile
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o
|
||||
|
||||
library: libhttp_parser.o
|
||||
$(CC) $(LDFLAGS_LIB) -o $(SONAME) $<
|
||||
|
||||
package: http_parser.o
|
||||
$(AR) rcs libhttp_parser.a http_parser.o
|
||||
|
||||
url_parser: http_parser.o contrib/url_parser.c
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@
|
||||
|
||||
url_parser_g: http_parser_g.o contrib/url_parser.c
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
|
||||
|
||||
parsertrace: http_parser.o contrib/parsertrace.c
|
||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace$(BINEXT)
|
||||
|
||||
parsertrace_g: http_parser_g.o contrib/parsertrace.c
|
||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g$(BINEXT)
|
||||
|
||||
tags: http_parser.c http_parser.h test.c
|
||||
ctags $^
|
||||
|
||||
install: library
|
||||
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
||||
$(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME)
|
||||
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
||||
|
||||
install-strip: library
|
||||
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
||||
$(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME)
|
||||
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
||||
|
||||
uninstall:
|
||||
rm $(INCLUDEDIR)/http_parser.h
|
||||
rm $(LIBDIR)/$(SONAME)
|
||||
rm $(LIBDIR)/libhttp_parser.so
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a tags test test_fast test_g \
|
||||
http_parser.tar libhttp_parser.so.* \
|
||||
url_parser url_parser_g parsertrace parsertrace_g \
|
||||
*.exe *.exe.so
|
||||
|
||||
contrib/url_parser.c: http_parser.h
|
||||
contrib/parsertrace.c: http_parser.h
|
||||
|
||||
.PHONY: clean package test-run test-run-timed test-valgrind install install-strip uninstall
|
||||
@@ -1,111 +0,0 @@
|
||||
/* Copyright Fedor Indutny. 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.
|
||||
*/
|
||||
#include "http_parser.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static const char data[] =
|
||||
"POST /joyent/http-parser HTTP/1.1\r\n"
|
||||
"Host: github.com\r\n"
|
||||
"DNT: 1\r\n"
|
||||
"Accept-Encoding: gzip, deflate, sdch\r\n"
|
||||
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n"
|
||||
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/39.0.2171.65 Safari/537.36\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,"
|
||||
"image/webp,*/*;q=0.8\r\n"
|
||||
"Referer: https://github.com/joyent/http-parser\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n\r\n";
|
||||
static const size_t data_len = sizeof(data) - 1;
|
||||
|
||||
static int on_info(http_parser* p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int on_data(http_parser* p, const char *at, size_t length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static http_parser_settings settings = {
|
||||
.on_message_begin = on_info,
|
||||
.on_headers_complete = on_info,
|
||||
.on_message_complete = on_info,
|
||||
.on_header_field = on_data,
|
||||
.on_header_value = on_data,
|
||||
.on_url = on_data,
|
||||
.on_status = on_data,
|
||||
.on_body = on_data
|
||||
};
|
||||
|
||||
int bench(int iter_count, int silent) {
|
||||
struct http_parser parser;
|
||||
int i;
|
||||
int err;
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
float rps;
|
||||
|
||||
if (!silent) {
|
||||
err = gettimeofday(&start, NULL);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < iter_count; i++) {
|
||||
size_t parsed;
|
||||
http_parser_init(&parser, HTTP_REQUEST);
|
||||
|
||||
parsed = http_parser_execute(&parser, &settings, data, data_len);
|
||||
assert(parsed == data_len);
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
err = gettimeofday(&end, NULL);
|
||||
assert(err == 0);
|
||||
|
||||
fprintf(stdout, "Benchmark result:\n");
|
||||
|
||||
rps = (float) (end.tv_sec - start.tv_sec) +
|
||||
(end.tv_usec - start.tv_usec) * 1e-6f;
|
||||
fprintf(stdout, "Took %f seconds to run\n", rps);
|
||||
|
||||
rps = (float) iter_count / rps;
|
||||
fprintf(stdout, "%f req/sec\n", rps);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc == 2 && strcmp(argv[1], "infinite") == 0) {
|
||||
for (;;)
|
||||
bench(5000000, 1);
|
||||
return 0;
|
||||
} else {
|
||||
return bench(5000000, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. 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.
|
||||
*/
|
||||
|
||||
/* Dump what the parser finds to stdout as it happen */
|
||||
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int on_message_begin(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE BEGIN***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_headers_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***HEADERS COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_message_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_url(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Url: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_field(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header field: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_value(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header value: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_body(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Body: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(const char* name) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s $type $filename\n"
|
||||
" type: -x, where x is one of {r,b,q}\n"
|
||||
" parses file as a Response, reQuest, or Both\n",
|
||||
name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
enum http_parser_type file_type;
|
||||
|
||||
if (argc != 3) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* type = argv[1];
|
||||
if (type[0] != '-') {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
switch (type[1]) {
|
||||
/* in the case of "-", type[1] will be NUL */
|
||||
case 'r':
|
||||
file_type = HTTP_RESPONSE;
|
||||
break;
|
||||
case 'q':
|
||||
file_type = HTTP_REQUEST;
|
||||
break;
|
||||
case 'b':
|
||||
file_type = HTTP_BOTH;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* filename = argv[2];
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
perror("fopen");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_length = ftell(file);
|
||||
if (file_length == -1) {
|
||||
perror("ftell");
|
||||
goto fail;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char* data = malloc(file_length);
|
||||
if (fread(data, 1, file_length, file) != (size_t)file_length) {
|
||||
fprintf(stderr, "couldn't read entire file\n");
|
||||
free(data);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
http_parser_settings settings;
|
||||
memset(&settings, 0, sizeof(settings));
|
||||
settings.on_message_begin = on_message_begin;
|
||||
settings.on_url = on_url;
|
||||
settings.on_header_field = on_header_field;
|
||||
settings.on_header_value = on_header_value;
|
||||
settings.on_headers_complete = on_headers_complete;
|
||||
settings.on_body = on_body;
|
||||
settings.on_message_complete = on_message_complete;
|
||||
|
||||
http_parser parser;
|
||||
http_parser_init(&parser, file_type);
|
||||
size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);
|
||||
free(data);
|
||||
|
||||
if (nparsed != (size_t)file_length) {
|
||||
fprintf(stderr,
|
||||
"Error: %s (%s)\n",
|
||||
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
|
||||
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
fail:
|
||||
fclose(file);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
dump_url (const char *url, const struct http_parser_url *u)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
||||
for (i = 0; i < UF_MAX; i++) {
|
||||
if ((u->field_set & (1 << i)) == 0) {
|
||||
printf("\tfield_data[%u]: unset\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tfield_data[%u]: off: %u, len: %u, part: %.*s\n",
|
||||
i,
|
||||
u->field_data[i].off,
|
||||
u->field_data[i].len,
|
||||
u->field_data[i].len,
|
||||
url + u->field_data[i].off);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
struct http_parser_url u;
|
||||
int len, connect, result;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("Syntax : %s connect|get url\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
len = strlen(argv[2]);
|
||||
connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
|
||||
printf("Parsing %s, connect %d\n", argv[2], connect);
|
||||
|
||||
http_parser_url_init(&u);
|
||||
result = http_parser_parse_url(argv[2], len, connect, &u);
|
||||
if (result != 0) {
|
||||
printf("Parse error : %d\n", result);
|
||||
return result;
|
||||
}
|
||||
printf("Parse ok, result : \n");
|
||||
dump_url(argv[2], &u);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
# This file is used with the GYP meta build system.
|
||||
# http://code.google.com/p/gyp/
|
||||
# To build try this:
|
||||
# svn co http://gyp.googlecode.com/svn/trunk gyp
|
||||
# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp
|
||||
# ./out/Debug/test
|
||||
{
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
# TODO: hoist these out and put them somewhere common, because
|
||||
# RuntimeLibrary MUST MATCH across the entire project
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 1, # static debug
|
||||
},
|
||||
},
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O3' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 0, # static release
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'defines': [
|
||||
'WIN32'
|
||||
],
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'http_parser',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'http_parser_strict',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-nonstrict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser' ],
|
||||
'sources': [ 'test.c' ]
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-strict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser_strict' ],
|
||||
'sources': [ 'test.c' ]
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,409 +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_MESSAGE_H_INCLUDED
|
||||
#define BEAST_HTTP_MESSAGE_H_INCLUDED
|
||||
|
||||
#include <beast/http/headers.h>
|
||||
#include <beast/http/method.h>
|
||||
#include <beast/asio/buffers_debug.h>
|
||||
#include <beast/asio/type_check.h>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct request_fields
|
||||
{
|
||||
http::method_t method;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
struct response_fields
|
||||
{
|
||||
int status;
|
||||
std::string reason;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
struct request_params
|
||||
{
|
||||
http::method_t method;
|
||||
std::string url;
|
||||
int version;
|
||||
};
|
||||
|
||||
struct response_params
|
||||
{
|
||||
int status;
|
||||
std::string reason;
|
||||
int version;
|
||||
};
|
||||
|
||||
/** A HTTP message.
|
||||
|
||||
A message can be a request or response, depending on the `isRequest`
|
||||
template argument value. Requests and responses have different types,
|
||||
so functions may be overloaded on them if desired.
|
||||
|
||||
The `Body` template argument type determines the model used
|
||||
to read or write the content body of the message.
|
||||
|
||||
@tparam isRequest `true` if this is a request.
|
||||
|
||||
@tparam Body A type meeting the requirements of Body.
|
||||
|
||||
@tparam Headers A type meeting the requirements of Headers.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
struct message
|
||||
: std::conditional_t<isRequest,
|
||||
detail::request_fields, detail::response_fields>
|
||||
{
|
||||
/** The trait type characterizing the body.
|
||||
|
||||
The body member will be of type body_type::value_type.
|
||||
*/
|
||||
using body_type = Body;
|
||||
using headers_type = Headers;
|
||||
|
||||
using is_request =
|
||||
std::integral_constant<bool, isRequest>;
|
||||
|
||||
int version; // 10 or 11
|
||||
headers_type headers;
|
||||
typename Body::value_type body;
|
||||
|
||||
message();
|
||||
message(message&&) = default;
|
||||
message(message const&) = default;
|
||||
message& operator=(message&&) = default;
|
||||
message& operator=(message const&) = default;
|
||||
|
||||
/** Construct a HTTP request.
|
||||
*/
|
||||
explicit
|
||||
message(request_params params);
|
||||
|
||||
/** Construct a HTTP response.
|
||||
*/
|
||||
explicit
|
||||
message(response_params params);
|
||||
|
||||
/// Serialize the request or response line to a Streambuf.
|
||||
template<class Streambuf>
|
||||
void
|
||||
write_firstline(Streambuf& streambuf) const
|
||||
{
|
||||
write_firstline(streambuf,
|
||||
std::integral_constant<bool, isRequest>{});
|
||||
}
|
||||
|
||||
/// Diagnostics only
|
||||
template<bool, class, class>
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message const& m);
|
||||
|
||||
private:
|
||||
template<class Streambuf>
|
||||
void
|
||||
write_firstline(Streambuf& streambuf,
|
||||
std::true_type) const;
|
||||
|
||||
template<class Streambuf>
|
||||
void
|
||||
write_firstline(Streambuf& streambuf,
|
||||
std::false_type) const;
|
||||
};
|
||||
|
||||
#if ! GENERATING_DOCS
|
||||
|
||||
/// A typical HTTP request
|
||||
template<class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using request = message<true, Body, Headers>;
|
||||
|
||||
/// A typical HTTP response
|
||||
template<class Body,
|
||||
class Headers = basic_headers<std::allocator<char>>>
|
||||
using response = message<false, Body, Headers>;
|
||||
|
||||
#endif
|
||||
|
||||
// For diagnostic output only
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& m);
|
||||
|
||||
/// Write a FieldSequence to a Streambuf.
|
||||
template<class Streambuf, class FieldSequence>
|
||||
void
|
||||
write_fields(Streambuf& streambuf, FieldSequence const& fields);
|
||||
|
||||
/// Returns `true` if a message indicates a keep alive
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
bool
|
||||
is_keep_alive(message<isRequest, Body, Headers> const& msg);
|
||||
|
||||
/// Returns `true` if a message indicates a HTTP Upgrade request or response
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
bool
|
||||
is_upgrade(message<isRequest, Body, Headers> const& msg);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#include <beast/http/impl/message.ipp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <beast/http/method.h>
|
||||
#include <beast/http/headers.h>
|
||||
#include <beast/ci_char_traits.h>
|
||||
#include <beast/http/detail/writes.h>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace deprecated_http {
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
} // deprecated_http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,282 +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_PARSER_H_INCLUDED
|
||||
#define BEAST_HTTP_PARSER_H_INCLUDED
|
||||
|
||||
#include <beast/http/basic_parser.h>
|
||||
#include <beast/http/error.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional>
|
||||
#include <beast/cxx17/type_traits.h> // <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A HTTP parser.
|
||||
|
||||
The parser may only be used once.
|
||||
*/
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
class parser
|
||||
: public basic_parser<parser<isRequest, Body, Headers>>
|
||||
{
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
|
||||
message_type m_;
|
||||
typename message_type::body_type::reader r_;
|
||||
bool started_ = false;
|
||||
|
||||
public:
|
||||
parser(parser&&) = default;
|
||||
|
||||
parser()
|
||||
: http::basic_parser<parser>(isRequest)
|
||||
, r_(m_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns `true` if at least one byte has been processed
|
||||
bool
|
||||
started()
|
||||
{
|
||||
return started_;
|
||||
}
|
||||
|
||||
message_type
|
||||
release()
|
||||
{
|
||||
return std::move(m_);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class http::basic_parser<parser>;
|
||||
|
||||
void
|
||||
on_start()
|
||||
{
|
||||
started_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
on_field(std::string const& field, std::string const& value)
|
||||
{
|
||||
m_.headers.insert(field, value);
|
||||
}
|
||||
|
||||
void
|
||||
on_headers_complete(error_code&)
|
||||
{
|
||||
// vFALCO TODO Decode the Content-Length and
|
||||
// Transfer-Encoding, see if we can reserve the buffer.
|
||||
//
|
||||
// r_.reserve(content_length)
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
{
|
||||
m_.method = method;
|
||||
m_.url = url;
|
||||
m_.version = major * 10 + minor;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t, std::string const&,
|
||||
int, int, bool, bool,
|
||||
std::false_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_request(http::method_t method, std::string const& url,
|
||||
int major, int minor, bool keep_alive, bool upgrade)
|
||||
{
|
||||
return on_request(method, url,
|
||||
major, minor, keep_alive, upgrade,
|
||||
typename message_type::is_request{});
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int status, std::string const& reason,
|
||||
int major, int minor, bool keep_alive, bool upgrade,
|
||||
std::true_type)
|
||||
{
|
||||
m_.status = status;
|
||||
m_.reason = reason;
|
||||
m_.version = major * 10 + minor;
|
||||
// VFALCO TODO return expect_body_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int, std::string const&, int, int, bool, bool,
|
||||
std::false_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
on_response(int status, std::string const& reason,
|
||||
int major, int minor, bool keep_alive, bool upgrade)
|
||||
{
|
||||
return on_response(
|
||||
status, reason, major, minor, keep_alive, upgrade,
|
||||
std::integral_constant<bool, ! message_type::is_request::value>{});
|
||||
}
|
||||
|
||||
void
|
||||
on_body(void const* data,
|
||||
std::size_t size, error_code& ec)
|
||||
{
|
||||
r_.write(data, size, ec);
|
||||
}
|
||||
|
||||
void
|
||||
on_complete()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// LEGACY
|
||||
//
|
||||
|
||||
#include <beast/http/basic_parser.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/body.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace deprecated_http {
|
||||
|
||||
/** Parser for HTTP messages.
|
||||
The result is stored in a message object.
|
||||
*/
|
||||
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
|
||||
@@ -1,46 +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_RESUME_CONTEXT_H_INCLUDED
|
||||
#define BEAST_HTTP_RESUME_CONTEXT_H_INCLUDED
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
/** A functor that resumes a write operation.
|
||||
|
||||
An rvalue reference to an object of this type is provided by the
|
||||
write implementation to the `writer` associated with the body of
|
||||
a message being sent.
|
||||
|
||||
If it is desired that the `writer` suspend the write operation (for
|
||||
example, to wait until data is ready), it can take ownership of
|
||||
the resume context using a move. Then, it returns `boost::indeterminate`
|
||||
to indicate that the write operation should suspend. Later, the calling
|
||||
code invokes the resume function and the write operation continues
|
||||
from where it left off.
|
||||
*/
|
||||
using resume_context = std::function<void(void)>;
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,90 +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 <beast/http/src/nodejs_parser.h>
|
||||
#include <beast/http/method.h>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4127) // conditional expression is constant
|
||||
# pragma warning (disable: 4244) // integer conversion, possible loss of data
|
||||
#endif
|
||||
#include <beast/http/impl/http-parser/http_parser.c>
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
beast::http::method_t
|
||||
convert_http_method(http_method m)
|
||||
{
|
||||
using namespace beast;
|
||||
switch (m)
|
||||
{
|
||||
case HTTP_DELETE: return http::method_t::http_delete;
|
||||
case HTTP_GET: return http::method_t::http_get;
|
||||
case HTTP_HEAD: return http::method_t::http_head;
|
||||
case HTTP_POST: return http::method_t::http_post;
|
||||
case HTTP_PUT: return http::method_t::http_put;
|
||||
|
||||
// pathological
|
||||
case HTTP_CONNECT: return http::method_t::http_connect;
|
||||
case HTTP_OPTIONS: return http::method_t::http_options;
|
||||
case HTTP_TRACE: return http::method_t::http_trace;
|
||||
|
||||
// webdav
|
||||
case HTTP_COPY: return http::method_t::http_copy;
|
||||
case HTTP_LOCK: return http::method_t::http_lock;
|
||||
case HTTP_MKCOL: return http::method_t::http_mkcol;
|
||||
case HTTP_MOVE: return http::method_t::http_move;
|
||||
case HTTP_PROPFIND: return http::method_t::http_propfind;
|
||||
case HTTP_PROPPATCH: return http::method_t::http_proppatch;
|
||||
case HTTP_SEARCH: return http::method_t::http_search;
|
||||
case HTTP_UNLOCK: return http::method_t::http_unlock;
|
||||
case HTTP_BIND: return http::method_t::http_bind;
|
||||
case HTTP_REBIND: return http::method_t::http_rebind;
|
||||
case HTTP_UNBIND: return http::method_t::http_unbind;
|
||||
case HTTP_ACL: return http::method_t::http_acl;
|
||||
|
||||
// subversion
|
||||
case HTTP_REPORT: return http::method_t::http_report;
|
||||
case HTTP_MKACTIVITY: return http::method_t::http_mkactivity;
|
||||
case HTTP_CHECKOUT: return http::method_t::http_checkout;
|
||||
case HTTP_MERGE: return http::method_t::http_merge;
|
||||
|
||||
// upnp
|
||||
case HTTP_MSEARCH: return http::method_t::http_msearch;
|
||||
case HTTP_NOTIFY: return http::method_t::http_notify;
|
||||
case HTTP_SUBSCRIBE: return http::method_t::http_subscribe;
|
||||
case HTTP_UNSUBSCRIBE: return http::method_t::http_unsubscribe;
|
||||
|
||||
// RFC-5789
|
||||
case HTTP_PATCH: return http::method_t::http_patch;
|
||||
case HTTP_PURGE: return http::method_t::http_purge;
|
||||
|
||||
// CalDav
|
||||
case HTTP_MKCALENDAR: return http::method_t::http_mkcalendar;
|
||||
|
||||
// RFC-2068, section 19.6.1.2
|
||||
case HTTP_LINK: return http::method_t::http_link;
|
||||
case HTTP_UNLINK: return http::method_t::http_unlink;
|
||||
};
|
||||
|
||||
return http::method_t::http_get;
|
||||
}
|
||||
@@ -1,45 +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_NODEJS_PARSER_H_INCLUDED
|
||||
#define BEAST_HTTP_NODEJS_PARSER_H_INCLUDED
|
||||
|
||||
#include <beast/http/method.h>
|
||||
#include <beast/http/impl/http-parser/http_parser.h>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
beast::http::method_t
|
||||
convert_http_method(http_method m);
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum<http_errno>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum<http_errno>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -1,94 +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 <beast/http/message.h>
|
||||
#include <beast/http/parser.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <utility>
|
||||
|
||||
namespace beast {
|
||||
namespace deprecated_http {
|
||||
namespace test {
|
||||
|
||||
class parser_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
message
|
||||
request(std::string const& text)
|
||||
{
|
||||
body b;
|
||||
message m;
|
||||
parser p(m, b, true);
|
||||
auto const used =
|
||||
p.write(boost::asio::buffer(text));
|
||||
expect(used == text.size());
|
||||
p.write_eof();
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
test_headers()
|
||||
{
|
||||
beast::http::headers<std::allocator<char>> h;
|
||||
h.insert("Field", "Value");
|
||||
expect (h.erase("Field") == 1);
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
test_headers();
|
||||
|
||||
{
|
||||
std::string const text =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"\r\n"
|
||||
;
|
||||
body b;
|
||||
message m;
|
||||
parser p (m, b, true);
|
||||
auto const used = p.write(
|
||||
boost::asio::buffer(text));
|
||||
expect(used == text.size());
|
||||
p.write_eof();
|
||||
expect(p.complete());
|
||||
}
|
||||
|
||||
{
|
||||
// malformed
|
||||
std::string const text =
|
||||
"GET\r\n"
|
||||
"\r\n"
|
||||
;
|
||||
body b;
|
||||
message m;
|
||||
parser p(m, b, true);
|
||||
boost::system::error_code ec;
|
||||
p.write(boost::asio::buffer(text), ec);
|
||||
if(expect(ec))
|
||||
expect(ec.message() == "invalid HTTP method");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(parser,http,beast);
|
||||
|
||||
} // test
|
||||
} // deprecated_http
|
||||
} // beast
|
||||
@@ -1,84 +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_TYPE_CHECK_H_INCLUDED
|
||||
#define BEAST_HTTP_TYPE_CHECK_H_INCLUDED
|
||||
|
||||
#include <beast/http/error.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/resume_context.h>
|
||||
#include <beast/asio/type_check.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <functional>
|
||||
#include <beast/cxx17/type_traits.h> // <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
#if GENERATING_DOCS
|
||||
namespace detail {
|
||||
#else
|
||||
namespace concept {
|
||||
#endif
|
||||
|
||||
struct Reader
|
||||
{
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
Reader(message<isRequest, Body, Headers>&) noexcept;
|
||||
void write(void const*, std::size_t, error_code&) noexcept;
|
||||
};
|
||||
|
||||
} // concept
|
||||
|
||||
/// Evaluates to std::true_type if `T` models Body
|
||||
template<class T>
|
||||
struct is_Body : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a reader
|
||||
template<class T>
|
||||
struct is_ReadableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evalulates to std::true_type if Body has a writer
|
||||
template<class T>
|
||||
struct is_WritableBody : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `T` models HTTPMessage
|
||||
template<class T>
|
||||
struct is_HTTPMessage : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
/// Evaluates to std::true_type if `HTTPMessage` is a request
|
||||
template<class HTTPMessage>
|
||||
struct is_HTTPRequest : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,32 +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_STREAMS_ABSTRACT_OSTREAM_H_INCLUDED
|
||||
#define BEAST_STREAMS_ABSTRACT_OSTREAM_H_INCLUDED
|
||||
|
||||
#include <beast/streams/basic_abstract_ostream.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** An abstract ostream for `char`. */
|
||||
using abstract_ostream = basic_abstract_ostream <char>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,73 +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_STREAMS_BASIC_STD_OSTREAM_H_INCLUDED
|
||||
#define BEAST_STREAMS_BASIC_STD_OSTREAM_H_INCLUDED
|
||||
|
||||
#include <beast/streams/basic_abstract_ostream.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace beast {
|
||||
|
||||
/** Wraps an existing std::basic_ostream as an abstract_ostream. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>
|
||||
>
|
||||
class basic_std_ostream
|
||||
: public basic_abstract_ostream <CharT, Traits>
|
||||
{
|
||||
private:
|
||||
using typename basic_abstract_ostream <CharT, Traits>::string_type;
|
||||
|
||||
std::reference_wrapper <std::ostream> m_stream;
|
||||
|
||||
public:
|
||||
explicit basic_std_ostream (
|
||||
std::basic_ostream <CharT, Traits>& stream)
|
||||
: m_stream (stream)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
m_stream.get() << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
using std_ostream = basic_std_ostream <char>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Returns a basic_std_ostream using template argument deduction. */
|
||||
template <
|
||||
class CharT,
|
||||
class Traits = std::char_traits <CharT>
|
||||
>
|
||||
basic_std_ostream <CharT, Traits>
|
||||
make_std_ostream (std::basic_ostream <CharT, Traits>& stream)
|
||||
{
|
||||
return basic_std_ostream <CharT, Traits> (stream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,91 +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_STREAMS_DEBUG_OSTREAM_H_INCLUDED
|
||||
#define BEAST_STREAMS_DEBUG_OSTREAM_H_INCLUDED
|
||||
|
||||
#include <beast/streams/abstract_ostream.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef WIN32_LEAN_AND_MEAN // VC_EXTRALEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# else
|
||||
#include <windows.h>
|
||||
# endif
|
||||
# ifdef min
|
||||
# undef min
|
||||
# endif
|
||||
# ifdef max
|
||||
# undef max
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace beast {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/** A basic_abstract_ostream that redirects output to an attached debugger. */
|
||||
class debug_ostream
|
||||
: public abstract_ostream
|
||||
{
|
||||
private:
|
||||
bool m_debugger;
|
||||
|
||||
public:
|
||||
debug_ostream()
|
||||
: m_debugger (IsDebuggerPresent() != FALSE)
|
||||
{
|
||||
// Note that the check for an attached debugger is made only
|
||||
// during construction time, for efficiency. A stream created before
|
||||
// the debugger is attached will not have output redirected.
|
||||
}
|
||||
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
if (m_debugger)
|
||||
{
|
||||
OutputDebugStringA ((s + "\n").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
class debug_ostream
|
||||
: public abstract_ostream
|
||||
{
|
||||
public:
|
||||
void
|
||||
write (string_type const& s) override
|
||||
{
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,66 +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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#if BEAST_INCLUDE_BEASTCONFIG
|
||||
#include "../../BeastConfig.h"
|
||||
#endif
|
||||
|
||||
#include <beast/streams/basic_abstract_ostream.h>
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
class basic_abstract_ostream_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
class test_stream : public basic_abstract_ostream <char>
|
||||
{
|
||||
public:
|
||||
test_stream&
|
||||
operator= (test_stream const&) = delete;
|
||||
|
||||
explicit
|
||||
test_stream (unit_test::suite& suite_)
|
||||
: m_suite (suite_)
|
||||
{
|
||||
}
|
||||
|
||||
void write (string_type const& s) override
|
||||
{
|
||||
m_suite.log << s;
|
||||
}
|
||||
|
||||
private:
|
||||
unit_test::suite& m_suite;
|
||||
};
|
||||
|
||||
void run()
|
||||
{
|
||||
test_stream ts (*this);
|
||||
|
||||
ts << "Hello";
|
||||
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(basic_abstract_ostream,streams,beast);
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
@@ -1,35 +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_UNIT_TEST_H_INCLUDED
|
||||
#define BEAST_UNIT_TEST_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/amount.h>
|
||||
#include <beast/unit_test/print.h>
|
||||
#include <beast/unit_test/global_suites.h>
|
||||
#include <beast/unit_test/match.h>
|
||||
#include <beast/unit_test/recorder.h>
|
||||
#include <beast/unit_test/reporter.h>
|
||||
#include <beast/unit_test/results.h>
|
||||
#include <beast/unit_test/runner.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <beast/unit_test/suite_info.h>
|
||||
#include <beast/unit_test/suite_list.h>
|
||||
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
# beast.unit_test
|
||||
|
||||
This provides a framework for defining and running unit tests.
|
||||
@@ -1,67 +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_UNIT_TEST_AMOUNT_H_INCLUDED
|
||||
#define BEAST_UNIT_TEST_AMOUNT_H_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** Utility for producing nicely composed output of amounts with units. */
|
||||
class amount
|
||||
{
|
||||
private:
|
||||
std::size_t n_;
|
||||
std::string const& what_;
|
||||
|
||||
public:
|
||||
amount (amount const&) = default;
|
||||
amount& operator= (amount const&) = delete;
|
||||
|
||||
template <class = void>
|
||||
amount (std::size_t n, std::string const& what);
|
||||
|
||||
friend
|
||||
std::ostream&
|
||||
operator<< (std::ostream& s, amount const& t);
|
||||
};
|
||||
|
||||
template <class>
|
||||
amount::amount (std::size_t n, std::string const& what)
|
||||
: n_ (n)
|
||||
, what_ (what)
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<< (std::ostream& s, amount const& t)
|
||||
{
|
||||
s << t.n_ << " " << t.what_ << ((t.n_ != 1) ? "s" : "");
|
||||
return s;
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,68 +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_UNIT_TEST_GLOBAL_SUITES_H_INCLUDED
|
||||
#define BEAST_UNIT_TEST_GLOBAL_SUITES_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/suite_list.h>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class = void>
|
||||
suite_list&
|
||||
global_suites()
|
||||
{
|
||||
static suite_list s;
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Suite>
|
||||
struct insert_suite
|
||||
{
|
||||
template <class = void>
|
||||
insert_suite (char const* name, char const* module,
|
||||
char const* library, bool manual);
|
||||
};
|
||||
|
||||
template <class Suite>
|
||||
template <class>
|
||||
insert_suite<Suite>::insert_suite (char const* name,
|
||||
char const* module, char const* library, bool manual)
|
||||
{
|
||||
global_suites().insert <Suite> (
|
||||
name, module, library, manual);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** Holds suites registered during static initialization. */
|
||||
inline
|
||||
suite_list const&
|
||||
global_suites()
|
||||
{
|
||||
return detail::global_suites();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,80 +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_UNIT_TEST_PRINT_H_INCLUDED
|
||||
#define BEAST_UNIT_TEST_PRINT_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/amount.h>
|
||||
#include <beast/unit_test/results.h>
|
||||
|
||||
#include <beast/streams/abstract_ostream.h>
|
||||
#include <beast/streams/basic_std_ostream.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace beast {
|
||||
namespace unit_test {
|
||||
|
||||
/** Write test results to the specified output stream. */
|
||||
/** @{ */
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, abstract_ostream& stream)
|
||||
{
|
||||
for (auto const& s : r)
|
||||
{
|
||||
for (auto const& c : s)
|
||||
{
|
||||
stream <<
|
||||
s.name() <<
|
||||
(c.name().empty() ? "" : ("." + c.name()));
|
||||
|
||||
std::size_t i (1);
|
||||
for (auto const& t : c.tests)
|
||||
{
|
||||
if (! t.pass)
|
||||
stream <<
|
||||
"#" << i <<
|
||||
" failed: " << t.reason;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream <<
|
||||
amount (r.size(), "suite") << ", " <<
|
||||
amount (r.cases(), "case") << ", " <<
|
||||
amount (r.total(), "test") << " total, " <<
|
||||
amount (r.failed(), "failure")
|
||||
;
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
void
|
||||
print (results const& r, std::ostream& stream = std::cout)
|
||||
{
|
||||
auto s (make_std_ostream (stream));
|
||||
print (r, s);
|
||||
}
|
||||
|
||||
} // unit_test
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,22 +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 <beast/asio/src/test/beast_asio_bind_handler_test.cpp>
|
||||
#include <beast/asio/src/test/beast_asio_buffers_test.cpp>
|
||||
#include <beast/asio/src/test/beast_asio_error_test.cpp>
|
||||
@@ -1,21 +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 <beast/clock/tests/beast_abstract_clock_test.cpp>
|
||||
#include <beast/clock/tests/beast_basic_seconds_clock_test.cpp>
|
||||
@@ -1,21 +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 <beast/crypto/tests/beast_base64_test.cpp>
|
||||
|
||||
@@ -1,29 +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 <beast/hash/xxhasher.h>
|
||||
#include <beast/hash/impl/spookyv2.cpp>
|
||||
|
||||
#if ! BEAST_NO_XXHASH
|
||||
#include <beast/hash/impl/xxhash.c>
|
||||
#endif
|
||||
#include <beast/hash/impl/siphash.cpp>
|
||||
|
||||
#include <beast/hash/tests/hash_append_test.cpp>
|
||||
#include <beast/hash/tests/hash_speed_test.cpp>
|
||||
@@ -1,27 +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 <beast/http/src/test/beast_http_chunked_encoder_test.cpp>
|
||||
#include <beast/http/src/test/beast_http_message_test.cpp>
|
||||
#include <beast/http/src/test/beast_http_parser_test.cpp>
|
||||
#include <beast/http/src/test/beast_http_rfc2616_test.cpp>
|
||||
|
||||
// VFALCO Must come last otherwise Windows 10 SDK
|
||||
// gets a compile error in winnt.h
|
||||
#include <beast/http/src/beast_http_nodejs_parser.cpp>
|
||||
@@ -1,20 +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 <beast/streams/tests/beast_basic_abstract_ostream_test.cpp>
|
||||
@@ -1,20 +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 <beast/test/beast_empty_base_optimization_test.cpp>
|
||||
@@ -1,21 +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 <beast/wsproto/src/test/beast_wsproto_ws_test.cpp>
|
||||
#include <beast/wsproto/src/test/beast_wsproto_ws_echo_test.cpp>
|
||||
@@ -1,30 +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_WSPROTO_H_INCLUDED
|
||||
#define BEAST_WSPROTO_H_INCLUDED
|
||||
|
||||
#include <beast/wsproto/error.h>
|
||||
#include <beast/wsproto/option.h>
|
||||
#include <beast/wsproto/rfc6455.h>
|
||||
#include <beast/wsproto/socket.h>
|
||||
#include <beast/wsproto/static_string.h>
|
||||
#include <beast/wsproto/teardown.h>
|
||||
|
||||
#endif
|
||||
@@ -1,232 +0,0 @@
|
||||
# Beast.WSProto
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Beast.WSProto provides developers with a robust WebSocket implementation
|
||||
built on Boost.Asio with a consistent asynchronous model using a modern
|
||||
C++ approach.
|
||||
|
||||
## Introduction
|
||||
|
||||
Today's web applications increasingly rely on alternatives to standard HTTP
|
||||
to achieve performance and/or responsiveness. While WebSocket implementations
|
||||
are widely available in common web development languages such as Javascript,
|
||||
good implementations in C++ are scarce. A survey of existing C++ WebSocket
|
||||
solutions reveals interfaces which have performance limitations, place
|
||||
unecessary restrictions on callers, exhibit excess complexity, and fail to
|
||||
take advantage of C++ features or the underlying network transport.
|
||||
|
||||
Beast.WSProto is built on Boost.Asio, a robust cross platform networking
|
||||
framework that is part of Boost and also offered as a standalone library.
|
||||
A proposal to add networking functionality to the C++ standard library,
|
||||
based on Boost.Asio, is under consideration by the standards committee.
|
||||
Since the final approved networking interface for the C++ standard library
|
||||
will likely closely resemble the current interface of Boost.Asio, it is
|
||||
logical for Beast.WSProto to use Boost.Asio as its network transport.
|
||||
|
||||
Beast.WSProto addresses the following goals:
|
||||
|
||||
* **Ease of Use.** WSProto offers only one socket object, whose interface
|
||||
resembles that of Boost.Asio socket as closely as possible. Users familiar
|
||||
with Boost.Asio will be immediately comfortable using a `wsproto::socket`.
|
||||
|
||||
* **Flexibility.** Library interfaces should provide callers with maximum
|
||||
flexibility in implementation; Important decisions such as how to manage
|
||||
buffers or be notified of completed asynchronous operations should be made
|
||||
by callers not the library.
|
||||
|
||||
* **Performance.** The implementation should achieve the highest level
|
||||
of performance possible, with no penalty for using abstractions.
|
||||
|
||||
* **Scalability.** The library should facilitate the development of
|
||||
network applications that scale to thousands of concurrent connections.
|
||||
|
||||
* **Efficiency.** The library should support techniques such as
|
||||
scatter-gather I/O, and allow programs to minimise data copying.
|
||||
|
||||
* **Basis for further abstraction.** The library should permit the
|
||||
development of other libraries that provide higher levels of abstraction.
|
||||
|
||||
Beast.WSProto takes advantage of Boost.Asio's universal Asynchronous
|
||||
model, handler allocation, and handler invocation hooks. Calls to wsproto
|
||||
asynchronous initiation functions allow callers the choice of using a
|
||||
completion handler, stackful or stackless coroutines, futures, or user
|
||||
defined customizations (for example, Boost.Fiber). The implementation
|
||||
uses handler invocation hooks (`asio_handler_invoke`), providing
|
||||
execution guarantees on composed operations in a manner identical to
|
||||
Boost.Asio. The implementation also uses handler allocation hooks
|
||||
(`asio_handler_allocate`) when allocating memory internally for composed
|
||||
operations.
|
||||
|
||||
There is no need for inheritance or virtual members in `wsproto::socket`.
|
||||
All operations are templated and transparent to the compiler, allowing for
|
||||
maximum inlining and optimization.
|
||||
|
||||
## Usage
|
||||
|
||||
All examples and identifiers mentioned in this document are written as
|
||||
if the following declarations are in effect:
|
||||
```C++
|
||||
#include <beast/wsproto.h>
|
||||
using namespace beast;
|
||||
using namespace boost::asio;
|
||||
```
|
||||
|
||||
### Creating a Socket
|
||||
|
||||
To participate in a WebSocket connection, callers create an instance
|
||||
of `wsproto::socket` templated on the `Stream` argument, which must meet
|
||||
the requirements of `AsyncReadStream`, `AsyncWriteStream`, `SyncReadStream`,
|
||||
and `SyncWriteStream`. Examples of types that meet these requirements are
|
||||
`ip::tcp::socket` and `ssl::stream<...>`:
|
||||
```c++
|
||||
io_service ios;
|
||||
wsproto::socket<ip::tcp::socket> ws1(ios); // owns the socket
|
||||
|
||||
ssl::context ctx(ssl::context::sslv23);
|
||||
wsproto::socket<ssl::stream<
|
||||
ip::tcp::socket>> wss(ios, ctx); // owns the socket
|
||||
|
||||
ip::tcp::socket sock(ios);
|
||||
wsproto::socket<ip::tcp::socket&> ws2(sock); // does not own the socket
|
||||
```
|
||||
|
||||
### Connection Establishment
|
||||
|
||||
Callers are responsible for performing tasks such as connection establishment
|
||||
before attempting websocket activities.
|
||||
```c++
|
||||
io_service ios;
|
||||
wsproto::socket<ip::tcp::socket> ws(ios);
|
||||
ws.next_layer().connect(ip::tcp::endpoint(
|
||||
ip::tcp::address::from_string("127.0.0.1"), 80));
|
||||
```
|
||||
|
||||
### WebSocket Handshake
|
||||
|
||||
After the connection is established, the socket may be used to initiate
|
||||
or accept a WebSocket Update request.
|
||||
|
||||
```c++
|
||||
// send a WebSocket Upgrade request.
|
||||
ws.handshake();
|
||||
```
|
||||
|
||||
### Sending and Receiving Messages
|
||||
|
||||
After the WebSocket handshake is accomplished, callers may send and receive
|
||||
messages using the message oriented interface:
|
||||
```c++
|
||||
void echo(wsproto::socket<ip::tcp::socket>& ws)
|
||||
{
|
||||
streambuf sb;
|
||||
wsproto::opcode op;
|
||||
wsproto::read(ws, op, sb);
|
||||
wsproto::write(ws, op, sb.data());
|
||||
sb.consume(sb.size());
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, callers may process incoming message data
|
||||
incrementally:
|
||||
```c++
|
||||
void echo(wsproto::socket<ip::tcp::socket>& ws)
|
||||
{
|
||||
streambuf sb;
|
||||
wsproto::msg_info mi{};
|
||||
for(;;)
|
||||
{
|
||||
ws.read_some(mi, sb);
|
||||
if(mi.fin)
|
||||
break;
|
||||
}
|
||||
wsproto::write(ws, op, sb.data());
|
||||
}
|
||||
```
|
||||
|
||||
### Asynchronous Completions, Coroutines, and Futures
|
||||
|
||||
Asynchronous versions are available for all functions:
|
||||
```c++
|
||||
wsproto::async_read(ws, sb, std::bind(
|
||||
&on_read, beast::asio::placeholders::error));
|
||||
```
|
||||
|
||||
Calls to WSProto asynchronous initiation functions support
|
||||
asio-style completion handlers, and other completion tokens
|
||||
such as support for coroutines or futures:
|
||||
```c++
|
||||
void echo(wsproto::socket<ip::tcp::socket>& ws,
|
||||
boost::asio::yield_context yield)
|
||||
{
|
||||
wsproto::async_read(ws, sb, yield);
|
||||
std::future<wsproto::error_code> fut =
|
||||
wsproto::async_write(ws, sb.data(), boost::use_future);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation
|
||||
|
||||
### Buffers
|
||||
|
||||
Because calls to read WebSocket data may return a variable amount of bytes,
|
||||
the interface to calls that read data require an object that meets the
|
||||
requirements of `Streambuf`. This concept is modeled on
|
||||
`boost::asio::basic_streambuf`, which meets the requirements of `Streambuf`
|
||||
defined below.
|
||||
|
||||
The `Streambuf` concept is intended to permit the following implementation
|
||||
strategies:
|
||||
|
||||
* A single contiguous character array, which is reallocated as necessary to
|
||||
accommodate changes in the size of the byte sequence. This is the
|
||||
implementation approach currently used in `boost::asio::basic_streambuf`.
|
||||
* A sequence of one or more byte arrays, where each array is of the same
|
||||
size. Additional byte array objects are appended to the sequence to
|
||||
accommodate changes in the size of the byte sequence.
|
||||
* A sequence of one or more byte arrays of varying sizes. Additional byte
|
||||
array objects are appended to the sequence to accommodate changes in the
|
||||
size of the byte sequence. This is the implementation approach currently
|
||||
used in `beast::basic_streambuf`.
|
||||
|
||||
#### `Streambuf` requirements:
|
||||
|
||||
In the table below, `X` denotes a class, `a` denotes a value
|
||||
of type `X`, `n` denotes a value convertible to `std::size_t`,
|
||||
and `U` and `T` denote unspecified types.
|
||||
|
||||
expression | return | type assertion/note/pre/post-condition
|
||||
------------------------- | ------------- | --------------------------------------
|
||||
`X::const_buffers_type` | `T` | `T` meets the requirements for `ConstBufferSequence`.
|
||||
`X::mutable_buffers_type` | `U` | `U` meets the requirements for `MutableBufferSequence`.
|
||||
`a.commit(n)` | | Moves bytes from the output sequence to the input sequence.
|
||||
`a.consume(n)` | | Removes bytes from the input sequence.
|
||||
`a.data()` | `T` | Returns a list of buffers that represents the input sequence.
|
||||
`a.prepare(n)` | `U` | Returns a list of buffers that represents the output sequence, with the given size.
|
||||
`a.size()` | `std::size_t` | Returns the size of the input sequence.
|
||||
`a.max_size()` | `std::size_t` | Returns the maximum size of the `Streambuf`.
|
||||
|
||||
### Thread Safety
|
||||
|
||||
Like a regular asio socket, a `wsproto::socket` is not thread safe. Callers are
|
||||
responsible for synchronizing operations on the socket using an implicit or
|
||||
explicit strand, as per the Asio documentation. A `wsproto::socket` supports
|
||||
one active read and one active write at the same time (caller initiated close,
|
||||
ping, and pong operations count as a write).
|
||||
|
||||
### Buffering
|
||||
|
||||
The implementation does not perform queueing or buffering of messages. If desired,
|
||||
these features should be implemented by callers. The impact of this design is
|
||||
that the caller is in full control of the allocation strategy used to store
|
||||
data and the back-pressure applied on the read and write side of the underlying
|
||||
TCP/IP connection.
|
||||
|
||||
### The `io_service`
|
||||
|
||||
The creation and operation of the `boost::asio::io_service` associated with the
|
||||
Stream object underlying the `wsproto::socket` is completely left up to the
|
||||
user of the library, permitting any implementation strategy including one that
|
||||
does not require threads for environments where threads are unavailable.
|
||||
Beast.WSProto itself does not use or require threads.
|
||||
@@ -1,66 +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_WSPROTO_HYBI13_H_INCLUDED
|
||||
#define BEAST_WSPROTO_HYBI13_H_INCLUDED
|
||||
|
||||
#include <beast/crypto/base64.h>
|
||||
#include <beast/crypto/sha.h>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
namespace detail {
|
||||
|
||||
template<class Gen>
|
||||
std::string
|
||||
make_sec_ws_key(Gen& g)
|
||||
{
|
||||
union U
|
||||
{
|
||||
std::array<std::uint32_t, 4> a4;
|
||||
std::array<std::uint8_t, 16> a16;
|
||||
};
|
||||
U u;
|
||||
for(int i = 0; i < 4; ++i)
|
||||
u.a4[i] = g();
|
||||
return base64_encode(u.a16.data(), u.a16.size());
|
||||
}
|
||||
|
||||
template<class = void>
|
||||
std::string
|
||||
make_sec_ws_accept(boost::string_ref const& key)
|
||||
{
|
||||
std::string s(key.data(), key.size());
|
||||
s += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
beast::sha_hasher h;
|
||||
h(s.data(), s.size());
|
||||
auto const digest = static_cast<
|
||||
beast::sha_hasher::result_type>(h);
|
||||
return base64_encode(digest.data(), digest.size());
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // wsproto
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,72 +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_WSPROTO_ERROR_H_INCLUDED
|
||||
#define BEAST_WSPROTO_ERROR_H_INCLUDED
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
/// Error values
|
||||
enum class error
|
||||
{
|
||||
/// Both sides performed a WebSocket close
|
||||
closed = 1,
|
||||
|
||||
/// WebSocket connection failed, protocol violation
|
||||
failed,
|
||||
|
||||
/// Upgrade request failed, connection is closed
|
||||
handshake_failed,
|
||||
|
||||
/// Upgrade request failed, but connection is still open
|
||||
keep_alive,
|
||||
|
||||
/// HTTP response is malformed
|
||||
response_malformed,
|
||||
|
||||
/// HTTP response failed the upgrade
|
||||
response_failed,
|
||||
|
||||
/// Upgrade request denied for invalid fields.
|
||||
response_denied,
|
||||
|
||||
/// Upgrade request is malformed
|
||||
request_malformed,
|
||||
|
||||
/// Upgrade request fields incorrect
|
||||
request_invalid,
|
||||
|
||||
/// Upgrade request denied
|
||||
request_denied
|
||||
};
|
||||
|
||||
error_code
|
||||
make_error_code(error e);
|
||||
|
||||
} // wsproto
|
||||
} // beast
|
||||
|
||||
#include <beast/wsproto/impl/error.ipp>
|
||||
|
||||
#endif
|
||||
@@ -1,39 +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_WSPROTO_ERROR_IPP_H_INCLUDED
|
||||
#define BEAST_WSPROTO_ERROR_IPP_H_INCLUDED
|
||||
|
||||
#include <beast/wsproto/detail/error.h>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
|
||||
inline
|
||||
error_code
|
||||
make_error_code(error e)
|
||||
{
|
||||
return error_code(
|
||||
static_cast<int>(e), detail::get_error_category());
|
||||
}
|
||||
|
||||
} // wsproto
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,285 +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_WSPROTO_ASYNC_ECHO_PEER_H_INCLUDED
|
||||
#define BEAST_WSPROTO_ASYNC_ECHO_PEER_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <beast/unit_test/thread.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/wsproto.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
namespace test {
|
||||
|
||||
// Asynchronous WebSocket echo client/server
|
||||
//
|
||||
class async_echo_peer
|
||||
{
|
||||
public:
|
||||
static std::size_t constexpr autobahnCycles = 520;
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
using address_type = boost::asio::ip::address;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
|
||||
private:
|
||||
unit_test::suite& suite_;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
std::vector<unit_test::thread> thread_;
|
||||
std::size_t n_ = 0;
|
||||
|
||||
public:
|
||||
async_echo_peer(bool server,
|
||||
endpoint_type const& ep, unit_test::suite& suite)
|
||||
: suite_(suite)
|
||||
, sock_(ios_)
|
||||
, acceptor_(ios_)
|
||||
{
|
||||
if(server)
|
||||
{
|
||||
error_code ec;
|
||||
acceptor_.open(ep.protocol(), ec);
|
||||
maybe_throw(ec, "open");
|
||||
acceptor_.bind(ep, ec);
|
||||
maybe_throw(ec, "bind");
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
maybe_throw(ec, "listen");
|
||||
acceptor_.async_accept(sock_,
|
||||
std::bind(&async_echo_peer::on_accept, this,
|
||||
beast::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
Peer{std::move(sock_), ep, suite_};
|
||||
}
|
||||
auto const n = 1;
|
||||
thread_.reserve(n);
|
||||
for(int i = 0; i < n; ++i)
|
||||
thread_.emplace_back(suite_,
|
||||
[&] { ios_.run(); });
|
||||
}
|
||||
|
||||
~async_echo_peer()
|
||||
{
|
||||
error_code ec;
|
||||
ios_.dispatch(
|
||||
[&]{ acceptor_.close(ec); });
|
||||
for(auto& t : thread_)
|
||||
t.join();
|
||||
}
|
||||
|
||||
private:
|
||||
class Peer
|
||||
{
|
||||
struct data
|
||||
{
|
||||
int state = 0;
|
||||
unit_test::suite& suite;
|
||||
boost::optional<endpoint_type> ep;
|
||||
wsproto::socket<socket_type> ws;
|
||||
wsproto::opcode op;
|
||||
beast::streambuf sb;
|
||||
int id;
|
||||
|
||||
data(socket_type&& sock_,
|
||||
unit_test::suite& suite_)
|
||||
: suite(suite_)
|
||||
, ws(std::move(sock_))
|
||||
, id([]
|
||||
{
|
||||
static int n = 0;
|
||||
return ++n;
|
||||
}())
|
||||
{
|
||||
}
|
||||
|
||||
data(socket_type&& sock_, endpoint_type const& ep_,
|
||||
unit_test::suite& suite_)
|
||||
: suite(suite_)
|
||||
, ep(ep_)
|
||||
, ws(std::move(sock_))
|
||||
, id([]
|
||||
{
|
||||
static int n = 0;
|
||||
return ++n;
|
||||
}())
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<data> d_;
|
||||
|
||||
public:
|
||||
Peer(Peer&&) = default;
|
||||
Peer(Peer const&) = default;
|
||||
Peer& operator=(Peer&&) = delete;
|
||||
Peer& operator=(Peer const&) = delete;
|
||||
|
||||
struct identity
|
||||
{
|
||||
template<class Body, class Headers>
|
||||
void
|
||||
operator()(http::message<true, Body, Headers>& req)
|
||||
{
|
||||
req.headers.replace("User-Agent", "async_echo_client");
|
||||
}
|
||||
|
||||
template<class Body, class Headers>
|
||||
void
|
||||
operator()(http::message<false, Body, Headers>& resp)
|
||||
{
|
||||
resp.headers.replace("Server", "async_echo_server");
|
||||
}
|
||||
};
|
||||
|
||||
template<class... Args>
|
||||
explicit
|
||||
Peer(socket_type&& sock, Args&&... args)
|
||||
: d_(std::make_shared<data>(
|
||||
std::forward<socket_type>(sock),
|
||||
std::forward<Args>(args)...))
|
||||
{
|
||||
auto& d = *d_;
|
||||
d.ws.set_option(decorate(identity{}));
|
||||
//d.ws.set_option(auto_fragment_size(0));
|
||||
d.ws.set_option(read_message_max(64 * 1024 * 1024));
|
||||
run();
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
auto& d = *d_;
|
||||
if(! d.ep)
|
||||
{
|
||||
d.ws.async_accept(std::move(*this));
|
||||
}
|
||||
else
|
||||
{
|
||||
d.state = 4;
|
||||
d.ws.next_layer().async_connect(
|
||||
*d.ep, std::move(*this));
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(error_code ec)
|
||||
{
|
||||
auto& d = *d_;
|
||||
switch(d_->state)
|
||||
{
|
||||
// did accept
|
||||
case 0:
|
||||
if(ec)
|
||||
return fail(ec, "async_accept");
|
||||
|
||||
// start
|
||||
case 1:
|
||||
if(ec)
|
||||
return fail(ec, "async_handshake");
|
||||
d.sb.consume(d.sb.size());
|
||||
// read message
|
||||
d.state = 2;
|
||||
d.ws.async_read(d.op, d.sb, std::move(*this));
|
||||
return;
|
||||
|
||||
// got message
|
||||
case 2:
|
||||
if(ec == wsproto::error::closed)
|
||||
return;
|
||||
if(ec)
|
||||
return fail(ec, "async_read");
|
||||
// write message
|
||||
d.state = 1;
|
||||
d.ws.set_option(wsproto::message_type(d.op));
|
||||
d.ws.async_write(d.sb.data(), std::move(*this));
|
||||
return;
|
||||
|
||||
// connected
|
||||
case 4:
|
||||
if(ec)
|
||||
return fail(ec, "async_connect");
|
||||
d.state = 1;
|
||||
d.ws.async_handshake(
|
||||
d.ep->address().to_string() + ":" +
|
||||
std::to_string(d.ep->port()),
|
||||
"/", std::move(*this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
if(ec != wsproto::error::closed)
|
||||
{
|
||||
d_->suite.log <<
|
||||
"#" << std::to_string(d_->id) << " " <<
|
||||
what << ": " << ec.message();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
suite_.log <<
|
||||
what << ": " << ec.message();
|
||||
}
|
||||
|
||||
void
|
||||
maybe_throw(error_code ec, std::string what)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, what);
|
||||
throw ec;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(error_code ec)
|
||||
{
|
||||
if(! acceptor_.is_open())
|
||||
return;
|
||||
maybe_throw(ec, "accept");
|
||||
socket_type sock(std::move(sock_));
|
||||
if(n_ < autobahnCycles)
|
||||
acceptor_.async_accept(sock_,
|
||||
std::bind(&async_echo_peer::on_accept, this,
|
||||
beast::asio::placeholders::error));
|
||||
Peer{std::move(sock), suite_};
|
||||
}
|
||||
};
|
||||
|
||||
} // test
|
||||
} // wsproto
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,94 +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 <beast/wsproto/src/test/async_echo_peer.h>
|
||||
#include <beast/wsproto/src/test/sync_echo_peer.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
namespace test {
|
||||
|
||||
class ws_echo_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
using address_type = boost::asio::ip::address;
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
async_echo_peer s1(true, endpoint_type{
|
||||
address_type::from_string("127.0.0.1"),
|
||||
6000 }, *this);
|
||||
|
||||
sync_echo_peer s2(true, endpoint_type{
|
||||
address_type::from_string("127.0.0.1"),
|
||||
6001 }, *this);
|
||||
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::signal_set signals(
|
||||
ios, SIGINT, SIGTERM);
|
||||
std::mutex m;
|
||||
bool stop = false;
|
||||
std::condition_variable cv;
|
||||
signals.async_wait(
|
||||
[&](boost::system::error_code const& ec,
|
||||
int signal_number)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
stop = true;
|
||||
cv.notify_one();
|
||||
});
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
cv.wait(lock, [&]{ return stop; });
|
||||
}
|
||||
};
|
||||
|
||||
class ws_client_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
using address_type = boost::asio::ip::address;
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
pass();
|
||||
{
|
||||
async_echo_peer s1(false, endpoint_type{
|
||||
address_type::from_string("127.0.0.1"),
|
||||
9001 }, *this);
|
||||
}
|
||||
{
|
||||
sync_echo_peer s2(false, endpoint_type{
|
||||
address_type::from_string("127.0.0.1"),
|
||||
9001 }, *this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(ws_echo, asio, beast);
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(ws_client, asio, beast);
|
||||
|
||||
} // test
|
||||
} // wsproto
|
||||
} // beast
|
||||
@@ -1,362 +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 <beast/wsproto/src/test/async_echo_peer.h>
|
||||
#include <beast/wsproto/src/test/sync_echo_peer.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <beast/unit_test/thread.h>
|
||||
#include <beast/http.h>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
|
||||
class ws_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
using error_code = boost::system::error_code;
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
using address_type = boost::asio::ip::address;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
using yield_context = boost::asio::yield_context;
|
||||
|
||||
endpoint_type ep_;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// opcodes for creating the test plans
|
||||
|
||||
// concurrent read and write
|
||||
struct case_1{};
|
||||
|
||||
// write a bad frame and shut down
|
||||
struct case_2{};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class coro_peer
|
||||
{
|
||||
error_code ec_;
|
||||
boost::asio::io_service ios_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
socket_type sock_;
|
||||
socket<socket_type&> ws_;
|
||||
opcode op_;
|
||||
beast::streambuf rb_;
|
||||
beast::streambuf wb_;
|
||||
yield_context* yield_;
|
||||
int state_ = 0;
|
||||
//unit_test::suite& test_;
|
||||
|
||||
public:
|
||||
coro_peer(coro_peer&&) = default;
|
||||
coro_peer(coro_peer const&) = delete;
|
||||
coro_peer& operator=(coro_peer&&) = delete;
|
||||
coro_peer& operator=(coro_peer const&) = delete;
|
||||
|
||||
template<class... Ops>
|
||||
coro_peer(bool server, endpoint_type ep,
|
||||
unit_test::suite& test, Ops const&... ops)
|
||||
: acceptor_(ios_)
|
||||
, sock_(ios_)
|
||||
, ws_(sock_)
|
||||
//, test_(test)
|
||||
{
|
||||
if(server)
|
||||
{
|
||||
acceptor_.open(ep.protocol());
|
||||
acceptor_.bind(ep);
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections);
|
||||
boost::asio::spawn(ios_,
|
||||
[=](auto yield)
|
||||
{
|
||||
yield_ = &yield;
|
||||
state_ = 10;
|
||||
acceptor_.async_accept(sock_, (*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return this->fail("accept");
|
||||
state_ = 20;
|
||||
ws_.async_accept((*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return this->fail("ws.accept");
|
||||
this->invoke(ops...);
|
||||
state_ = -1;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::asio::spawn(ios_,
|
||||
[=](auto yield)
|
||||
{
|
||||
yield_ = &yield;
|
||||
state_ = 30;
|
||||
sock_.async_connect(ep, (*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return this->fail("connect");
|
||||
state_ = 40;
|
||||
ws_.async_handshake(ep.address().to_string() +
|
||||
std::to_string(ep.port()), "/", (*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return this->fail("handshake");
|
||||
this->invoke(ops...);
|
||||
state_ = -1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
~coro_peer()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
void
|
||||
run_one()
|
||||
{
|
||||
ios_.run_one();
|
||||
}
|
||||
|
||||
void
|
||||
step_to(int to = 0)
|
||||
{
|
||||
while(state_ != to)
|
||||
ios_.run_one();
|
||||
}
|
||||
|
||||
private:
|
||||
template<class String>
|
||||
void fail(String const& s)
|
||||
{
|
||||
}
|
||||
|
||||
void invoke_1(case_1)
|
||||
{
|
||||
ws_.async_read(op_, rb_,
|
||||
[&](auto ec)
|
||||
{
|
||||
if(ec)
|
||||
return this->fail(ec);
|
||||
rb_.consume(rb_.size());
|
||||
});
|
||||
state_ = 100;
|
||||
ws_.async_write(
|
||||
boost::asio::null_buffers{}, (*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return fail("write");
|
||||
}
|
||||
|
||||
void invoke_1(case_2)
|
||||
{
|
||||
detail::frame_header fh;
|
||||
fh.op = opcode::rsv5; // bad opcode
|
||||
fh.fin = true;
|
||||
fh.mask = true;
|
||||
fh.rsv1 = false;
|
||||
fh.rsv2 = false;
|
||||
fh.rsv3 = false;
|
||||
fh.len = 0;
|
||||
fh.key = 0;
|
||||
detail::write(wb_, fh);
|
||||
state_ = 200;
|
||||
boost::asio::async_write(
|
||||
ws_.next_layer(), wb_.data(),
|
||||
(*yield_)[ec_]);
|
||||
if(ec_)
|
||||
return fail("write");
|
||||
ws_.next_layer().shutdown(
|
||||
socket_type::shutdown_both, ec_);
|
||||
if(ec_)
|
||||
return fail("shutdown");
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
invoke()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Op, class... Ops>
|
||||
inline
|
||||
void
|
||||
invoke(Op op, Ops const&... ops)
|
||||
{
|
||||
invoke_1(op);
|
||||
invoke(ops...);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testInvokable()
|
||||
{
|
||||
endpoint_type const ep{
|
||||
address_type::from_string(
|
||||
"127.0.0.1"), 6000};
|
||||
coro_peer server(true, ep, *this, case_1{});
|
||||
coro_peer client(false, ep, *this, case_2{});
|
||||
server.step_to(10); // async_accept
|
||||
client.step_to(30); // async_connect
|
||||
server.step_to(20); // async_accept(ws)
|
||||
client.step_to(40); // async_handshake
|
||||
server.step_to(100); // case_1
|
||||
client.step_to(200); // case_2
|
||||
client.step_to(-1);
|
||||
server.step_to(-1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
maybe_fail(error_code const& ec, std::string const& what)
|
||||
{
|
||||
return expect(! ec, what + ": " + ec.message());
|
||||
}
|
||||
|
||||
void
|
||||
maybe_throw(error_code ec, std::string what)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
maybe_fail(ec, what);
|
||||
throw ec;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Buffers>
|
||||
static
|
||||
std::string
|
||||
buffers_to_string(Buffers const& bs)
|
||||
{
|
||||
using boost::asio::buffer_cast;
|
||||
using boost::asio::buffer_size;
|
||||
std::string s;
|
||||
s.reserve(buffer_size(bs));
|
||||
for(auto const& b : bs)
|
||||
s.append(buffer_cast<char const*>(b),
|
||||
buffer_size(b));
|
||||
for(auto i = s.size(); i-- > 0;)
|
||||
if(s[i] == '\r')
|
||||
s.replace(i, 1, "\\r");
|
||||
else if(s[i] == '\n')
|
||||
s.replace(i, 1, "\\n\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
makeRequest(endpoint_type ep, std::string const& s)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ip::tcp::socket sock(ios);
|
||||
sock.connect(ep);
|
||||
write(sock, append_buffers(
|
||||
buffer(s), buffer("\r\n")));
|
||||
|
||||
using namespace http;
|
||||
response<string_body> resp;
|
||||
streambuf sb;
|
||||
read(sock, sb, resp);
|
||||
return resp.status;
|
||||
}
|
||||
|
||||
void
|
||||
expectStatus(endpoint_type ep,
|
||||
int status, std::string const& s)
|
||||
{
|
||||
expect(makeRequest(ep, s) == status);
|
||||
}
|
||||
|
||||
void
|
||||
testHandshake(endpoint_type ep)
|
||||
{
|
||||
expectStatus(ep, 400, "GET / HTTP/1.0\r\n");
|
||||
}
|
||||
|
||||
void
|
||||
syncEchoClient(endpoint_type ep)
|
||||
{
|
||||
using boost::asio::buffer;
|
||||
error_code ec;
|
||||
boost::asio::io_service ios;
|
||||
wsproto::socket<socket_type> ws(ios);
|
||||
ws.next_layer().connect(ep, ec);
|
||||
if(! maybe_fail(ec, "connect"))
|
||||
return;
|
||||
ws.handshake(ep.address().to_string(), "/", ec);
|
||||
if(! maybe_fail(ec, "upgrade"))
|
||||
return;
|
||||
std::string s(65535, '*');
|
||||
ws.write_frame(true, buffer(s), ec);
|
||||
if(! maybe_fail(ec, "write"))
|
||||
return;
|
||||
boost::asio::streambuf sb;
|
||||
wsproto::opcode op;
|
||||
ws.read(op, sb, ec);
|
||||
if(! maybe_fail(ec, "read"))
|
||||
return;
|
||||
if(! ec)
|
||||
expect(op == wsproto::opcode::text);
|
||||
expect(buffers_to_string(sb.data()) == s);
|
||||
sb.consume(sb.size());
|
||||
ws.close({}, ec);
|
||||
if(! maybe_fail(ec, "close"))
|
||||
return;
|
||||
while(! ec)
|
||||
{
|
||||
ws.read(op, sb, ec);
|
||||
if(! ec)
|
||||
sb.consume(sb.size());
|
||||
}
|
||||
if(ec != error::closed)
|
||||
maybe_fail(ec, "teardown");
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
//testInvokable();
|
||||
|
||||
{
|
||||
endpoint_type ep{
|
||||
address_type::from_string("127.0.0.1"), 6000};
|
||||
testcase("Echo Server");
|
||||
test::sync_echo_peer s(true, ep, *this);
|
||||
//testHandshake(ep);
|
||||
syncEchoClient(ep);
|
||||
}
|
||||
|
||||
{
|
||||
endpoint_type ep{
|
||||
address_type::from_string("127.0.0.1"), 6001};
|
||||
testcase("Async Echo Server");
|
||||
test::async_echo_peer s(true, ep, *this);
|
||||
//testHandshake(ep);
|
||||
syncEchoClient(ep);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(ws,asio,beast);
|
||||
|
||||
} // wsproto
|
||||
} // beast
|
||||
@@ -1,182 +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_WSPROTO_SYNC_ECHO_PEER_H_INCLUDED
|
||||
#define BEAST_WSPROTO_SYNC_ECHO_PEER_H_INCLUDED
|
||||
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/wsproto.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace beast {
|
||||
namespace wsproto {
|
||||
namespace test {
|
||||
|
||||
// Synchronous WebSocket echo client/server
|
||||
//
|
||||
class sync_echo_peer
|
||||
{
|
||||
public:
|
||||
static std::size_t constexpr autobahnCycles = 520;
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
||||
using address_type = boost::asio::ip::address;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
|
||||
private:
|
||||
unit_test::suite& suite_;
|
||||
boost::asio::io_service ios_;
|
||||
socket_type sock_;
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
unit_test::thread thread_;
|
||||
std::size_t n_ = 0;
|
||||
|
||||
public:
|
||||
sync_echo_peer(bool server,
|
||||
endpoint_type ep, unit_test::suite& suite)
|
||||
: suite_(suite)
|
||||
, sock_(ios_)
|
||||
, acceptor_(ios_)
|
||||
{
|
||||
error_code ec;
|
||||
acceptor_.open(ep.protocol(), ec);
|
||||
maybe_throw(ec, "open");
|
||||
acceptor_.bind(ep, ec);
|
||||
maybe_throw(ec, "bind");
|
||||
acceptor_.listen(
|
||||
boost::asio::socket_base::max_connections, ec);
|
||||
maybe_throw(ec, "listen");
|
||||
acceptor_.async_accept(sock_,
|
||||
std::bind(&sync_echo_peer::on_accept, this,
|
||||
beast::asio::placeholders::error));
|
||||
thread_ = unit_test::thread(suite_,
|
||||
[&]
|
||||
{
|
||||
ios_.run();
|
||||
});
|
||||
}
|
||||
|
||||
~sync_echo_peer()
|
||||
{
|
||||
error_code ec;
|
||||
ios_.dispatch(
|
||||
[&]{ acceptor_.close(ec); });
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
fail(error_code ec, std::string what)
|
||||
{
|
||||
suite_.log <<
|
||||
what << ": " << ec.message();
|
||||
}
|
||||
|
||||
void
|
||||
maybe_throw(error_code ec, std::string what)
|
||||
{
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, what);
|
||||
throw ec;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
on_accept(error_code ec)
|
||||
{
|
||||
if(ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
maybe_throw(ec, "accept");
|
||||
++n_;
|
||||
std::thread{
|
||||
[
|
||||
this,
|
||||
sock = std::move(sock_),
|
||||
work = boost::asio::io_service::work{ios_}
|
||||
]() mutable
|
||||
{
|
||||
do_peer(std::move(sock));
|
||||
}}.detach();
|
||||
if(n_ < autobahnCycles)
|
||||
acceptor_.async_accept(sock_,
|
||||
std::bind(&sync_echo_peer::on_accept, this,
|
||||
beast::asio::placeholders::error));
|
||||
}
|
||||
|
||||
struct identity
|
||||
{
|
||||
template<class Body, class Headers>
|
||||
void
|
||||
operator()(http::message<true, Body, Headers>& req)
|
||||
{
|
||||
req.headers.replace("User-Agent", "sync_echo_client");
|
||||
}
|
||||
|
||||
template<class Body, class Headers>
|
||||
void
|
||||
operator()(http::message<false, Body, Headers>& resp)
|
||||
{
|
||||
resp.headers.replace("Server", "sync_echo_server");
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
do_peer(socket_type&& sock)
|
||||
{
|
||||
wsproto::socket<socket_type> ws(std::move(sock));
|
||||
ws.set_option(decorate(identity{}));
|
||||
ws.set_option(read_message_max(64 * 1024 * 1024));
|
||||
//ws.set_option(auto_fragment_size(0));
|
||||
error_code ec;
|
||||
ws.accept(ec);
|
||||
if(ec)
|
||||
{
|
||||
fail(ec, "accept");
|
||||
return;
|
||||
}
|
||||
for(;;)
|
||||
{
|
||||
wsproto::opcode op;
|
||||
beast::streambuf sb;
|
||||
ws.read(op, sb, ec);
|
||||
if(ec)
|
||||
break;
|
||||
ws.set_option(wsproto::message_type(op));
|
||||
ws.write(sb.data(), ec);
|
||||
if(ec)
|
||||
break;
|
||||
}
|
||||
if(ec && ec != wsproto::error::closed)
|
||||
{
|
||||
fail(ec, "read");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // test
|
||||
} // wsproto
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -1,126 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_RANDOM_XOR_SHIFT_ENGINE_H_INCLUDED
|
||||
#define BEAST_RANDOM_XOR_SHIFT_ENGINE_H_INCLUDED
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class = void>
|
||||
class xor_shift_engine
|
||||
{
|
||||
public:
|
||||
using result_type = std::uint64_t;
|
||||
|
||||
xor_shift_engine(xor_shift_engine const&) = default;
|
||||
xor_shift_engine& operator=(xor_shift_engine const&) = default;
|
||||
|
||||
explicit
|
||||
xor_shift_engine (result_type val = 1977u);
|
||||
|
||||
void
|
||||
seed (result_type seed);
|
||||
|
||||
result_type
|
||||
operator()();
|
||||
|
||||
static
|
||||
result_type constexpr
|
||||
min()
|
||||
{
|
||||
return std::numeric_limits<result_type>::min();
|
||||
}
|
||||
|
||||
static
|
||||
result_type constexpr
|
||||
max()
|
||||
{
|
||||
return std::numeric_limits<result_type>::max();
|
||||
}
|
||||
|
||||
private:
|
||||
result_type s_[2];
|
||||
|
||||
static
|
||||
result_type
|
||||
murmurhash3 (result_type x);
|
||||
};
|
||||
|
||||
template <class _>
|
||||
xor_shift_engine<_>::xor_shift_engine (
|
||||
result_type val)
|
||||
{
|
||||
seed (val);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
void
|
||||
xor_shift_engine<_>::seed (result_type seed)
|
||||
{
|
||||
if (seed == 0)
|
||||
throw std::domain_error("invalid seed");
|
||||
s_[0] = murmurhash3 (seed);
|
||||
s_[1] = murmurhash3 (s_[0]);
|
||||
}
|
||||
|
||||
template <class _>
|
||||
auto
|
||||
xor_shift_engine<_>::operator()() ->
|
||||
result_type
|
||||
{
|
||||
result_type s1 = s_[0];
|
||||
result_type const s0 = s_[1];
|
||||
s_[0] = s0;
|
||||
s1 ^= s1 << 23;
|
||||
return (s_[1] = (s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26))) + s0;
|
||||
}
|
||||
|
||||
template <class _>
|
||||
auto
|
||||
xor_shift_engine<_>::murmurhash3 (result_type x)
|
||||
-> result_type
|
||||
{
|
||||
x ^= x >> 33;
|
||||
x *= 0xff51afd7ed558ccdULL;
|
||||
x ^= x >> 33;
|
||||
x *= 0xc4ceb9fe1a85ec53ULL;
|
||||
return x ^= x >> 33;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
/** XOR-shift Generator.
|
||||
|
||||
Meets the requirements of UniformRandomNumberGenerator.
|
||||
|
||||
Simple and fast RNG based on:
|
||||
http://xorshift.di.unimi.it/xorshift128plus.c
|
||||
does not accept seed==0
|
||||
*/
|
||||
using xor_shift_engine = detail::xor_shift_engine<>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,17 +8,17 @@
|
||||
import os ;
|
||||
|
||||
exe http_crawl :
|
||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
||||
../src/beast_http_nodejs_parser.cpp
|
||||
http_crawl.cpp
|
||||
urls_large_data.cpp
|
||||
;
|
||||
|
||||
exe http_server :
|
||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
||||
../src/beast_http_nodejs_parser.cpp
|
||||
http_server.cpp
|
||||
;
|
||||
|
||||
exe wsproto_echo :
|
||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
||||
../src/beast_http_nodejs_parser.cpp
|
||||
wsproto_echo.cpp
|
||||
;
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/http/resume_context.h>
|
||||
#include <beast/http/message.hpp>
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user