Reorganize source files

This commit is contained in:
Vinnie Falco
2016-04-19 20:29:16 -04:00
parent 54f6f0ceba
commit f07cd8ceb4
239 changed files with 2692 additions and 19127 deletions

4
.gitignore vendored
View File

@@ -23,8 +23,4 @@ contents.xcworkspacedata
.DS_Store
.svn
profile
Builds/VisualStudio2012/Debug
Builds/VisualStudio2012/Release
project.xcworkspace
modules/beast_cryptopp
bin/

View File

@@ -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

View File

@@ -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

View File

@@ -48,6 +48,7 @@ else
project beast
: requirements
<include>.
<include>./include
#<use>/boost//headers
<library>/boost/system//boost_system
<library>/boost/filesystem//boost_filesystem

View File

@@ -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/

View File

@@ -1,8 +1,22 @@
* kick out non-beast code
* redo directory structure
* Change build options to C++11 only
* Replace Jamroot with Jamfile
* Switch source material to Boost license
* Fix failing test/message.cpp
* Complete allocator testing in basic_streambuf, basic_headers
* Tidy up type_checks
- Derive from std::integral_constant
* Check DOXYGEN, GENERATIC_DOCS directives in source
- See if we can include them now that xsl is fixed
* Go over each header and split header material into detail and impl files
* Make buffers_debug a detail
* Ensure each public header has a unit test .cpp file
* Roll header-only http parser
* Define Parser concept in HTTP
* melpon sandbox?
* invokable unit test
* trim public interface of rfc2616.h to essentials only
* Use new http routines in JSONRPCClient
* Remove or change http::headers alias

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
git-subtree: "http-parser"
remote: https://github.com/joyent/http-parser.git
branch: master

View File

@@ -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

View File

@@ -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>

View File

@@ -1,13 +0,0 @@
language: c
compiler:
- clang
- gcc
script:
- "make"
notifications:
email: false
irc:
- "irc.freenode.net#node-ci"

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -1,3 +0,0 @@
# beast.unit_test
This provides a framework for defining and running unit tests.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -8,17 +8,17 @@
import os ;
exe http_crawl :
../beast/http/src/beast_http_nodejs_parser.cpp
../src/beast_http_nodejs_parser.cpp
http_crawl.cpp
urls_large_data.cpp
;
exe http_server :
../beast/http/src/beast_http_nodejs_parser.cpp
../src/beast_http_nodejs_parser.cpp
http_server.cpp
;
exe wsproto_echo :
../beast/http/src/beast_http_nodejs_parser.cpp
../src/beast_http_nodejs_parser.cpp
wsproto_echo.cpp
;

View File

@@ -20,8 +20,8 @@
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
#include <beast/http/message.h>
#include <beast/http/resume_context.h>
#include <beast/http/message.hpp>
#include <beast/http/resume_context.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/filesystem.hpp>
#include <cstdio>

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