mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-25 21:15:49 +00:00
Reorganize source files
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -23,8 +23,4 @@ contents.xcworkspacedata
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.svn
|
.svn
|
||||||
profile
|
profile
|
||||||
Builds/VisualStudio2012/Debug
|
|
||||||
Builds/VisualStudio2012/Release
|
|
||||||
project.xcworkspace
|
|
||||||
modules/beast_cryptopp
|
|
||||||
bin/
|
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
|
project beast
|
||||||
: requirements
|
: requirements
|
||||||
<include>.
|
<include>.
|
||||||
|
<include>./include
|
||||||
#<use>/boost//headers
|
#<use>/boost//headers
|
||||||
<library>/boost/system//boost_system
|
<library>/boost/system//boost_system
|
||||||
<library>/boost/filesystem//boost_filesystem
|
<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
|
* kick out non-beast code
|
||||||
|
|
||||||
* redo directory structure
|
* redo directory structure
|
||||||
|
|
||||||
* Change build options to C++11 only
|
* Change build options to C++11 only
|
||||||
|
|
||||||
* Replace Jamroot with Jamfile
|
* 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 ;
|
import os ;
|
||||||
|
|
||||||
exe http_crawl :
|
exe http_crawl :
|
||||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
../src/beast_http_nodejs_parser.cpp
|
||||||
http_crawl.cpp
|
http_crawl.cpp
|
||||||
urls_large_data.cpp
|
urls_large_data.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe http_server :
|
exe http_server :
|
||||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
../src/beast_http_nodejs_parser.cpp
|
||||||
http_server.cpp
|
http_server.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
exe wsproto_echo :
|
exe wsproto_echo :
|
||||||
../beast/http/src/beast_http_nodejs_parser.cpp
|
../src/beast_http_nodejs_parser.cpp
|
||||||
wsproto_echo.cpp
|
wsproto_echo.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/http/message.h>
|
#include <beast/http/message.hpp>
|
||||||
#include <beast/http/resume_context.h>
|
#include <beast/http/resume_context.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <cstdio>
|
#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