summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/spirit/workbench
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/spirit/workbench
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/spirit/workbench')
-rw-r--r--src/boost/libs/spirit/workbench/boilerplate.cpp35
-rw-r--r--src/boost/libs/spirit/workbench/high_resolution_timer.hpp473
-rw-r--r--src/boost/libs/spirit/workbench/karma/Jamfile15
-rw-r--r--src/boost/libs/spirit/workbench/karma/double_performance.cpp169
-rw-r--r--src/boost/libs/spirit/workbench/karma/format_performance.cpp172
-rw-r--r--src/boost/libs/spirit/workbench/karma/int_generator.cpp129
-rw-r--r--src/boost/libs/spirit/workbench/karma/real_generator.cpp106
-rw-r--r--src/boost/libs/spirit/workbench/karma/sequence_performance.cpp70
-rw-r--r--src/boost/libs/spirit/workbench/measure.hpp136
-rw-r--r--src/boost/libs/spirit/workbench/qi/Jamfile19
-rw-r--r--src/boost/libs/spirit/workbench/qi/attr_vs_actions.cpp98
-rw-r--r--src/boost/libs/spirit/workbench/qi/int_parser.cpp106
-rw-r--r--src/boost/libs/spirit/workbench/qi/keywords.cpp553
-rw-r--r--src/boost/libs/spirit/workbench/qi/keywords.hpp49
-rw-r--r--src/boost/libs/spirit/workbench/qi/real_parser.cpp118
-rw-r--r--src/boost/libs/spirit/workbench/x3/context.cpp51
-rw-r--r--src/boost/libs/spirit/workbench/x3/toy/toy.cpp247
17 files changed, 2546 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/workbench/boilerplate.cpp b/src/boost/libs/spirit/workbench/boilerplate.cpp
new file mode 100644
index 00000000..9759ac38
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/boilerplate.cpp
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#include "measure.hpp"
+
+namespace
+{
+ struct f : test::base
+ {
+ void benchmark()
+ {
+ this->val += 5; // Here is where you put code that you want
+ // to benchmark. Make sure it returns something.
+ // Anything.
+ }
+ };
+}
+
+int main()
+{
+ BOOST_SPIRIT_TEST_BENCHMARK(
+ 10000000, // This is the maximum repetitions to execute
+ (f) // Place your tests here. For now, we have only one test: (f)
+ // If you have 3 tests a, b and c, this line will contain (a)(b)(c)
+ )
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/high_resolution_timer.hpp b/src/boost/libs/spirit/workbench/high_resolution_timer.hpp
new file mode 100644
index 00000000..b06a42ad
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/high_resolution_timer.hpp
@@ -0,0 +1,473 @@
+// Copyright (c) 2005-2010 Hartmut Kaiser
+// Copyright (c) 2009 Edward Grace
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM)
+#define HIGH_RESOLUTION_TIMER_MAR_24_2008_1222PM
+
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+
+#if defined(BOOST_HAS_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <time.h>
+#include <stdexcept>
+#include <limits>
+
+#if defined(BOOST_WINDOWS)
+
+#include <windows.h>
+
+namespace util
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ // CAUTION: Windows only!
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ {
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ start_time.QuadPart = (LONGLONG)(t * frequency.QuadPart);
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+
+ FILETIME ft;
+ SystemTimeToFileTime(&st, &ft);
+
+ LARGE_INTEGER now;
+ now.LowPart = ft.dwLowDateTime;
+ now.HighPart = ft.dwHighDateTime;
+
+ // FileTime is in 100ns increments, result needs to be in [s]
+ return now.QuadPart * 1e-7;
+ }
+
+ void restart()
+ {
+ if (!QueryPerformanceCounter(&start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ LARGE_INTEGER now;
+ if (!QueryPerformanceCounter(&now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return double(now.QuadPart - start_time.QuadPart) / frequency.QuadPart;
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return double((std::numeric_limits<LONGLONG>::max)() - start_time.QuadPart) /
+ double(frequency.QuadPart);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ LARGE_INTEGER frequency;
+ if (!QueryPerformanceFrequency(&frequency))
+ boost::throw_exception(std::runtime_error("Couldn't acquire frequency"));
+
+ return 1.0 / frequency.QuadPart;
+ }
+
+ private:
+ LARGE_INTEGER start_time;
+ };
+
+} // namespace util
+
+#elif defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_THREAD_CPUTIME)
+
+#if _POSIX_THREAD_CPUTIME > 0 // timer always supported
+
+namespace util
+{
+
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ {
+ start_time.tv_sec = 0;
+ start_time.tv_nsec = 0;
+
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ {
+ start_time.tv_sec = time_t(t);
+ start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
+ }
+
+ void restart()
+ {
+ if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ if (now.tv_sec == start_time.tv_sec)
+ return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
+
+ return double(now.tv_sec - start_time.tv_sec) +
+ (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ timespec resolution;
+ if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution"));
+ return double(resolution.tv_sec + resolution.tv_nsec * 1e-9);
+ }
+
+ private:
+ timespec start_time;
+ };
+
+} // namespace util
+
+#else // _POSIX_THREAD_CPUTIME > 0
+
+#include <boost/timer.hpp>
+
+// availability of high performance timers must be checked at runtime
+namespace util
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ public:
+ high_resolution_timer()
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
+ {
+ if (!use_backup) {
+ start_time.tv_sec = 0;
+ start_time.tv_nsec = 0;
+ }
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0)
+ {
+ if (!use_backup) {
+ start_time.tv_sec = time_t(t);
+ start_time.tv_nsec = (t - start_time.tv_sec) * 1e9;
+ }
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : use_backup(sysconf(_SC_THREAD_CPUTIME) <= 0),
+ start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ if (sysconf(_SC_THREAD_CPUTIME) <= 0)
+ return double(std::clock());
+
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return double(now.tv_sec) + double(now.tv_nsec) * 1e-9;
+ }
+
+ void restart()
+ {
+ if (use_backup)
+ start_time_backup.restart();
+ else if (-1 == clock_gettime(CLOCK_REALTIME, &start_time))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+ double elapsed() const // return elapsed time in seconds
+ {
+ if (use_backup)
+ return start_time_backup.elapsed();
+
+ timespec now;
+ if (-1 == clock_gettime(CLOCK_REALTIME, &now))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+
+ if (now.tv_sec == start_time.tv_sec)
+ return double(now.tv_nsec - start_time.tv_nsec) * 1e-9;
+
+ return double(now.tv_sec - start_time.tv_sec) +
+ (double(now.tv_nsec - start_time.tv_nsec) * 1e-9);
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ if (use_backup)
+ start_time_backup.elapsed_max();
+
+ return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ if (use_backup)
+ start_time_backup.elapsed_min();
+
+ timespec resolution;
+ if (-1 == clock_getres(CLOCK_REALTIME, &resolution))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution"));
+ return double(resolution.tv_sec + resolution.tv_nsec * 1e-9);
+ }
+
+ private:
+ bool use_backup;
+ timespec start_time;
+ boost::timer start_time_backup;
+ };
+
+} // namespace util
+
+#endif // _POSIX_THREAD_CPUTIME > 0
+
+#else // !defined(BOOST_WINDOWS) && (!defined(_POSIX_TIMERS)
+ // || _POSIX_TIMERS <= 0
+ // || !defined(_POSIX_THREAD_CPUTIME)
+ // || _POSIX_THREAD_CPUTIME <= 0)
+
+#if defined(BOOST_HAS_GETTIMEOFDAY)
+
+// For platforms that do not support _POSIX_TIMERS but do have
+// GETTIMEOFDAY, which is still preferable to std::clock()
+#include <sys/time.h>
+
+namespace util
+{
+
+ ///////////////////////////////////////////////////////////////////////////
+ //
+ // high_resolution_timer
+ // A timer object measures elapsed time.
+ //
+ // Implemented with gettimeofday() for platforms that support it,
+ // such as Darwin (OS X) but do not support the previous options.
+ //
+ // Copyright (c) 2009 Edward Grace
+ //
+ ///////////////////////////////////////////////////////////////////////////
+ class high_resolution_timer
+ {
+ private:
+ template <typename U>
+ static inline double unsigned_diff(const U &a, const U &b)
+ {
+ if (a > b)
+ return static_cast<double>(a-b);
+ return -static_cast<double>(b-a);
+ }
+
+ // @brief Return the difference between two timeval types.
+ //
+ // @param t1 The most recent timeval.
+ // @param t0 The historical timeval.
+ //
+ // @return The difference between the two in seconds.
+ double elapsed(const timeval &t1, const timeval &t0) const
+ {
+ if (t1.tv_sec == t0.tv_sec)
+ return unsigned_diff(t1.tv_usec,t0.tv_usec) * 1e-6;
+
+ // We do it this way as the result of the difference of the
+ // microseconds can be negative if the clock is implemented so
+ // that the seconds timer increases in large steps.
+ //
+ // Naive subtraction of the unsigned types and conversion to
+ // double can wreak havoc!
+ return unsigned_diff(t1.tv_sec,t0.tv_sec) +
+ unsigned_diff(t1.tv_usec,t0.tv_usec) * 1e-6;
+ }
+
+ public:
+ high_resolution_timer()
+ {
+ start_time.tv_sec = 0;
+ start_time.tv_usec = 0;
+
+ restart();
+ }
+
+ high_resolution_timer(double t)
+ {
+ start_time.tv_sec = time_t(t);
+ start_time.tv_usec = (t - start_time.tv_sec) * 1e6;
+ }
+
+ high_resolution_timer(high_resolution_timer const& rhs)
+ : start_time(rhs.start_time)
+ {
+ }
+
+ static double now()
+ {
+ // Under some implementations gettimeofday() will always
+ // return zero. If it returns anything else however then
+ // we accept this as evidence of an error. Note we are
+ // not assuming that -1 explicitly indicates the error
+ // condition, just that non zero is indicative of the
+ // error.
+ timeval now;
+ if (gettimeofday(&now, NULL))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return double(now.tv_sec) + double(now.tv_usec) * 1e-6;
+ }
+
+ void restart()
+ {
+ if (gettimeofday(&start_time, NULL))
+ boost::throw_exception(std::runtime_error("Couldn't initialize start_time"));
+ }
+
+ double elapsed() const // return elapsed time in seconds
+ {
+ timeval now;
+ if (gettimeofday(&now, NULL))
+ boost::throw_exception(std::runtime_error("Couldn't get current time"));
+ return elapsed(now,start_time);
+ }
+
+ double elapsed_max() const // return estimated maximum value for elapsed()
+ {
+ return double((std::numeric_limits<time_t>::max)() - start_time.tv_sec);
+ }
+
+ double elapsed_min() const // return minimum value for elapsed()
+ {
+ // On systems without an explicit clock_getres or similar
+ // we can only estimate an upper bound on the resolution
+ // by repeatedly calling the gettimeofday function. This
+ // is often likely to be indicative of the true
+ // resolution.
+ timeval t0, t1;
+ double delta(0);
+
+ if (gettimeofday(&t0, NULL))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution."));
+
+ // Spin around in a tight loop until we observe a change
+ // in the reported timer value.
+ do {
+ if (gettimeofday(&t1, NULL))
+ boost::throw_exception(std::runtime_error("Couldn't get resolution."));
+ delta = elapsed(t1, t0);
+ } while (delta <= 0.0);
+
+ return delta;
+ }
+
+ private:
+ timeval start_time;
+ };
+
+}
+
+#else // BOOST_HAS_GETTIMEOFDAY
+
+// For platforms other than Windows or Linux, or not implementing gettimeofday
+// simply fall back to boost::timer
+#include <boost/timer.hpp>
+
+namespace util
+{
+ struct high_resolution_timer
+ : boost::timer
+ {
+ static double now()
+ {
+ return double(std::clock());
+ }
+ };
+}
+
+#endif
+
+#endif
+
+#endif // HIGH_RESOLUTION_TIMER_AUG_14_2009_0425PM
+
+//
+// $Log: high_resolution_timer.hpp,v $
+// Revision 1.4 2009/08/14 15:28:10 graceej
+// * It is entirely possible for the updating clock to increment the
+// * seconds and *decrement* the microseconds field. Consequently
+// * when subtracting these unsigned microseconds fields a wrap-around
+// * error can occur. For this reason elapsed(t1, t0) is used in a
+// * similar maner to cycle.h this preserves the sign of the
+// * difference.
+//
+
+
diff --git a/src/boost/libs/spirit/workbench/karma/Jamfile b/src/boost/libs/spirit/workbench/karma/Jamfile
new file mode 100644
index 00000000..e837c6d6
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/Jamfile
@@ -0,0 +1,15 @@
+#==============================================================================
+# Copyright (c) 2001-2010 Joel de Guzman
+# Copyright (c) 2001-2010 Hartmut Kaiser
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+project spirit-karma-benchmark ;
+
+# performance tests
+exe int_generator : int_generator.cpp ;
+exe real_generator : real_generator.cpp ;
+exe format_performance : format_performance.cpp ;
+exe double_performance : double_performance.cpp ;
+exe sequence_performance : sequence_performance.cpp ;
diff --git a/src/boost/libs/spirit/workbench/karma/double_performance.cpp b/src/boost/libs/spirit/workbench/karma/double_performance.cpp
new file mode 100644
index 00000000..e707c27c
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/double_performance.cpp
@@ -0,0 +1,169 @@
+// Copyright (c) 2002-2010 Hartmut Kaiser
+// Copyright (c) 2002-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/format.hpp>
+
+#include <iostream>
+
+#include "../high_resolution_timer.hpp"
+
+#define NUMITERATIONS 1000000
+
+///////////////////////////////////////////////////////////////////////////////
+// We generate plain floating point numbers in this test
+//[karma_double_performance_definitions
+using boost::spirit::karma::double_;
+//]
+
+void format_performance_karma()
+{
+ using boost::spirit::karma::generate;
+
+ //[karma_double_performance_plain
+ char buffer[256];
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+ generate(p, double_, 12345.12345);
+ *p = '\0';
+ }
+ //]
+
+ std::cout << "karma:\t\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_rule()
+{
+ using boost::spirit::karma::generate;
+
+ boost::spirit::karma::rule<char*, double()> r;
+
+ //[karma_double_performance_rule
+ char buffer[256];
+ r %= double_;
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+ generate(p, r, 12345.12345);
+ *p = '\0';
+ }
+ //]
+
+ std::cout << "karma (rule):\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_direct()
+{
+ using boost::spirit::karma::generate;
+ using boost::spirit::karma::real_inserter;
+
+ //[karma_double_performance_direct
+ typedef real_inserter<double> inserter;
+ char buffer[256];
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+ inserter::call(p, 12345.12345);
+ *p = '\0';
+ }
+ //]
+
+ std::cout << "karma (direct):\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_string()
+{
+ using boost::spirit::karma::generate;
+
+ //[karma_double_performance_string
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ generated.clear();
+ generate(sink, double_, 12345.12345);
+ }
+ //]
+
+ std::cout << "karma (string):\t" << t.elapsed() << std::endl;
+// std::cout << generated << std::endl;
+}
+
+// Boost.Format
+void format_performance_boost_format()
+{
+ //[karma_double_performance_format
+ std::string generated;
+ boost::format double_format("%f");
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i)
+ generated = boost::str(double_format % 12345.12345);
+ //]
+
+ std::cout << "format:\t\t" << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+void format_performance_sprintf()
+{
+ util::high_resolution_timer t;
+
+ //[karma_double_performance_printf
+ char buffer[256];
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ sprintf(buffer, "%f", 12345.12345);
+ }
+ //]
+
+ std::cout << "sprintf:\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_iostreams()
+{
+ //[karma_double_performance_iostreams
+ std::stringstream strm;
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+ strm << 12345.12345;
+ }
+ //]
+
+ std::cout << "iostreams:\t" << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ format_performance_sprintf();
+ format_performance_iostreams();
+ format_performance_boost_format();
+ format_performance_karma();
+ format_performance_string();
+ format_performance_rule();
+ format_performance_direct();
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/karma/format_performance.cpp b/src/boost/libs/spirit/workbench/karma/format_performance.cpp
new file mode 100644
index 00000000..ee17c681
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/format_performance.cpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2002-2010 Hartmut Kaiser
+// Copyright (c) 2002-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/format.hpp>
+
+#include <iostream>
+
+#include "../high_resolution_timer.hpp"
+
+#define NUMITERATIONS 1000000
+
+///////////////////////////////////////////////////////////////////////////////
+// policy for real_generator, which forces to output trailing zeros in the
+// fractional part
+//[karma_format_performance_definitions
+template <typename T>
+struct double3_policy : boost::spirit::karma::real_policies<T>
+{
+ // we want to generate up to 3 fractional digits
+ static unsigned int precision(T) { return 3; }
+};
+
+typedef boost::spirit::karma::real_generator<double, double3_policy<double> >
+ double3_type;
+double3_type const double3 = double3_type();
+//]
+
+void format_performance_karma()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ //[karma_format_performance_plain
+ char buffer[256];
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+ generate(p
+ , '[' << left_align(14)[double3] << left_align(14)[double3] << ']'
+ , 12345.12345, 12345.12345);
+ *p = '\0';
+ }
+ //]
+
+ std::cout << "karma:\t\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_rule()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ typedef boost::fusion::vector<double, double> rtype;
+ boost::spirit::karma::rule<char*, rtype()> r;
+
+ //[karma_format_performance_rule
+ char buffer[256];
+ r %= '[' << left_align(14)[double3] << left_align(14)[double3] << ']';
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ char *p = buffer;
+ generate(p, r, 12345.12345, 12345.12345);
+ *p = '\0';
+ }
+ //]
+
+ std::cout << "karma (rule):\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_string()
+{
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::generate;
+
+ //[karma_format_performance_string
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ generated.clear();
+ generate(sink
+ , '[' << left_align(14)[double3] << left_align(14)[double3] << ']'
+ , 12345.12345, 12345.12345);
+ }
+ //]
+
+ std::cout << "karma (string):\t" << t.elapsed() << std::endl;
+// std::cout << generated << std::endl;
+}
+
+// Boost.Format
+void format_performance_boost_format()
+{
+ //[karma_format_performance_format
+ std::string generated;
+ boost::format outformat("[%-14.3f%-14.3f]");
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i)
+ generated = boost::str(outformat % 12345.12345 % 12345.12345);
+ //]
+
+ std::cout << "format:\t\t" << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+void format_performance_sprintf()
+{
+ util::high_resolution_timer t;
+
+ //[karma_format_performance_printf
+ char buffer[256];
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ sprintf(buffer, "[%-14.3f%-14.3f]", 12345.12345, 12345.12345);
+ }
+ //]
+
+ std::cout << "sprintf:\t" << t.elapsed() << std::endl;
+// std::cout << buffer << std::endl;
+}
+
+void format_performance_iostreams()
+{
+ //[karma_format_performance_iostreams
+ std::stringstream strm;
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < NUMITERATIONS; ++i) {
+ strm.str("");
+ strm << '['
+ << std::setiosflags(std::ios::fixed)
+ << std::left
+ << std::setprecision(3)
+ << std::setw(14)
+ << 12345.12345
+ << std::setw(14)
+ << 12345.12345
+ << ']';
+ }
+ //]
+
+ std::cout << "iostreams:\t" << t.elapsed() << std::endl;
+// std::cout << strm.str() << std::endl;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ format_performance_sprintf();
+ format_performance_iostreams();
+ format_performance_boost_format();
+ format_performance_karma();
+ format_performance_string();
+ format_performance_rule();
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/karma/int_generator.cpp b/src/boost/libs/spirit/workbench/karma/int_generator.cpp
new file mode 100644
index 00000000..7c822a2c
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/int_generator.cpp
@@ -0,0 +1,129 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <climits>
+#include <cstdlib>
+
+#include <iostream>
+#include <sstream>
+#include <boost/format.hpp>
+
+#include "../high_resolution_timer.hpp"
+
+// This value specifies, how to unroll the integer string generation loop in
+// Karma.
+// Set this to some integer in between 0 (no unrolling) and max expected
+// integer string len (complete unrolling). If not specified, this value
+// defaults to 6.
+#define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
+
+#include <boost/spirit/include/karma.hpp>
+
+using namespace std;
+using namespace boost::spirit;
+
+#define MAX_ITERATION 10000000
+
+///////////////////////////////////////////////////////////////////////////////
+struct random_fill
+{
+ int operator()() const
+ {
+ int scale = std::rand() / 100 + 1;
+ return (std::rand() * std::rand()) / scale;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ cout << "Converting " << MAX_ITERATION
+ << " randomly generated int values to strings." << flush << endl;
+
+ std::srand(0);
+ std::vector<int> v (MAX_ITERATION);
+ std::generate(v.begin(), v.end(), random_fill()); // randomly fill the vector
+
+ // test the C libraries ltoa function (the most low level function for
+ // string conversion available)
+ {
+ //[karma_int_performance_ltoa
+ char buffer[65]; // we don't expect more than 64 bytes to be generated here
+ //<-
+ std::string str;
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ ltoa(v[i], buffer, 10);
+ //<-
+ str = buffer; // compensate for string ops in other benchmarks
+ //->
+ }
+ //]
+
+ cout << "ltoa:\t\t" << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the iostreams library
+ {
+ //[karma_int_performance_iostreams
+ std::stringstream str;
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ str.str("");
+ str << v[i];
+ }
+ //]
+
+ cout << "iostreams:\t" << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the Boost.Format library
+ {
+ //[karma_int_performance_format
+ std::string str;
+ boost::format int_format("%d");
+ //<-
+ util::high_resolution_timer t;
+ //->
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ str = boost::str(int_format % v[i]);
+ }
+ //]
+
+ cout << "Boost.Format:\t" << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the Karma int_ generation routines
+ {
+ std::string str;
+ util::high_resolution_timer t;
+
+ //[karma_int_performance_plain
+ char buffer[65]; // we don't expect more than 64 bytes to be generated here
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ char *ptr = buffer;
+ karma::generate(ptr, int_, v[i]);
+ *ptr = '\0';
+ //<-
+ str = buffer; // compensate for string ops in other benchmarks
+ //->
+ }
+ //]
+
+ cout << "int_:\t\t" << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/karma/real_generator.cpp b/src/boost/libs/spirit/workbench/karma/real_generator.cpp
new file mode 100644
index 00000000..43a29fde
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/real_generator.cpp
@@ -0,0 +1,106 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <climits>
+#include <cassert>
+
+#include <iostream>
+#include <sstream>
+#include <boost/format.hpp>
+
+#include <boost/spirit/include/karma.hpp>
+
+#include "../high_resolution_timer.hpp"
+
+using namespace std;
+using namespace boost::spirit;
+
+#define MAX_ITERATION 10000000
+
+///////////////////////////////////////////////////////////////////////////////
+struct random_fill
+{
+ double operator()() const
+ {
+ double scale = std::rand() / 100 + 1;
+ return double(std::rand() * std::rand()) / scale;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+ char buffer[512]; // we don't expect more than 512 bytes to be generated
+
+ cout << "Converting " << MAX_ITERATION
+ << " randomly generated double values to strings." << flush << endl;
+
+ std::srand(0);
+ std::vector<double> v (MAX_ITERATION);
+ std::generate(v.begin(), v.end(), random_fill()); // randomly fill the vector
+
+ // test the C libraries gcvt function (the most low level function for
+ // string conversion available)
+ {
+ std::string str;
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ gcvt(v[i], 10, buffer);
+ str = buffer; // compensate for string ops in other benchmarks
+ }
+
+ cout << "gcvt: " << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the iostreams library
+ {
+ std::stringstream str;
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ str.str("");
+ str << v[i];
+ }
+
+ cout << "iostreams: " << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the Boost.Format library
+ {
+ std::string str;
+ boost::format double_format("%f");
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ str = boost::str(double_format % v[i]);
+ }
+
+ cout << "Boost.Format: " << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ // test the Karma double_ generation routines
+ {
+ std::string str;
+ util::high_resolution_timer t;
+
+ for (int i = 0; i < MAX_ITERATION; ++i)
+ {
+ char *ptr = buffer;
+ karma::generate(ptr, double_, v[i]);
+ *ptr = '\0';
+ str = buffer; // compensate for string ops in other benchmarks
+ }
+
+ cout << "double_: " << t.elapsed() << " [s]" << flush << endl;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/karma/sequence_performance.cpp b/src/boost/libs/spirit/workbench/karma/sequence_performance.cpp
new file mode 100644
index 00000000..e54febd1
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/karma/sequence_performance.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) 2005-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#define FUSION_MAX_TUPLE_SIZE 10
+#define USE_FUSION_VECTOR
+
+#include <climits>
+
+#include <iostream>
+#include <boost/preprocessor/repeat.hpp>
+#include <boost/preprocessor/inc.hpp>
+
+#include <boost/spirit/include/karma.hpp>
+
+#include "../high_resolution_timer.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+static char const* const literal_sequences[] = {
+ "", "a", "ab", "abc", "abcd", "abcde",
+ "abcdef", "abcdefg", "abcdefgh", "abcdefghi", "abcdefgij"
+};
+
+///////////////////////////////////////////////////////////////////////////////
+#define MAX_ITERATION 10000000
+#define MAX_SEQUENCE_LENGTH 9
+#define RCHAR(z, n, _) char_((char)('a' + n)) <<
+
+#define SEQUENCE_TEST(z, N, _) \
+ { \
+ util::high_resolution_timer t; \
+ \
+ for (int i = 0; i < MAX_ITERATION; ++i) \
+ { \
+ char *ptr = buffer; \
+ generate(ptr, BOOST_PP_REPEAT(N, RCHAR, _) char_('\0')); \
+ } \
+ \
+ std::cout << "karma::sequence(" << BOOST_PP_INC(N) << "):\t" \
+ << std::setw(9) << t.elapsed() << "\t" \
+ << std::flush << std::endl; \
+ \
+ BOOST_ASSERT(std::string(buffer) == literal_sequences[N]); \
+ } \
+ /**/
+
+// double elapsed = t.elapsed(); \
+// for (int i = 0; i < MAX_ITERATION; ++i) \
+// { \
+// char *ptr = buffer; \
+// generate(ptr, lit(literal_sequences[N]) << char_('\0')); \
+// } \
+// \
+// t.restart(); \
+// \
+// << std::setw(9) << elapsed << " [s]" \
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ using namespace boost::spirit::karma;
+ using namespace boost::spirit::ascii;
+ char buffer[512]; // we don't expect more than 512 bytes to be generated here
+
+ std::cout << "Benchmarking sequence of different length: " << std::endl;
+ BOOST_PP_REPEAT_FROM_TO(1, MAX_SEQUENCE_LENGTH, SEQUENCE_TEST, _);
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/workbench/measure.hpp b/src/boost/libs/spirit/workbench/measure.hpp
new file mode 100644
index 00000000..3b3b1910
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/measure.hpp
@@ -0,0 +1,136 @@
+// Copyright David Abrahams, Matthias Troyer, Michael Gauckler
+// 2005. Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#if !defined(BOOST_SPIRIT_TEST_BENCHMARK_HPP)
+#define BOOST_SPIRIT_TEST_BENCHMARK_HPP
+
+#ifdef _MSC_VER
+// inline aggressively
+# pragma inline_recursion(on) // turn on inline recursion
+# pragma inline_depth(255) // max inline depth
+# define _SECURE_SCL 0
+#endif
+
+#include "high_resolution_timer.hpp"
+#include <iostream>
+#include <cstring>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+namespace test
+{
+ // This value is required to ensure that a smart compiler's dead
+ // code elimination doesn't optimize away anything we're testing.
+ // We'll use it to compute the return code of the executable to make
+ // sure it's needed.
+ int live_code;
+
+ // Call objects of the given Accumulator type repeatedly
+ template <class Accumulator>
+ void hammer(long const repeats)
+ {
+ // Strategy: because the sum in an accumulator after each call
+ // depends on the previous value of the sum, the CPU's pipeline
+ // might be stalled while waiting for the previous addition to
+ // complete. Therefore, we allocate an array of accumulators,
+ // and update them in sequence, so that there's no dependency
+ // between adjacent addition operations.
+ //
+ // Additionally, if there were only one accumulator, the
+ // compiler or CPU might decide to update the value in a
+ // register rather that writing it back to memory. we want each
+ // operation to at least update the L1 cache. *** Note: This
+ // concern is specific to the particular application at which
+ // we're targeting the test. ***
+
+ // This has to be at least as large as the number of
+ // simultaneous accumulations that can be executing in the
+ // compiler pipeline. A safe number here is larger than the
+ // machine's maximum pipeline depth. If you want to test the L2
+ // or L3 cache, or main memory, you can increase the size of
+ // this array. 1024 is an upper limit on the pipeline depth of
+ // current vector machines.
+
+ const std::size_t number_of_accumulators = 1024;
+ live_code = 0; // reset to zero
+
+ Accumulator a[number_of_accumulators];
+
+ for (long iteration = 0; iteration < repeats; ++iteration)
+ {
+ for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap)
+ {
+ ap->benchmark();
+ }
+ }
+
+ // Accumulate all the partial sums to avoid dead code
+ // elimination.
+ for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap)
+ {
+ live_code += ap->val;
+ }
+ }
+
+ // Measure the time required to hammer accumulators of the given type
+ template <class Accumulator>
+ double measure(long const repeats)
+ {
+ // Hammer accumulators a couple of times to ensure the
+ // instruction cache is full of our test code, and that we don't
+ // measure the cost of a page fault for accessing the data page
+ // containing the memory where the accumulators will be
+ // allocated
+ hammer<Accumulator>(repeats);
+ hammer<Accumulator>(repeats);
+
+ // Now start a timer
+ util::high_resolution_timer time;
+ hammer<Accumulator>(repeats); // This time, we'll measure
+ return time.elapsed(); // return the elapsed time
+ }
+
+ template <class Accumulator>
+ void report(char const* name, long const repeats)
+ {
+ std::cout.precision(10);
+ std::cout << name << ": ";
+ for (int i = 0; i < (20-int(strlen(name))); ++i)
+ std::cout << ' ';
+ std::cout << std::fixed << test::measure<Accumulator>(repeats) << " [s] ";
+ Accumulator acc;
+ acc.benchmark();
+ std::cout << std::hex << "{checksum: " << acc.val << "}";
+ std::cout << std::flush << std::endl;
+ }
+
+ struct base
+ {
+ base() : val(0) {}
+ int val; // This is needed to avoid dead-code elimination
+ };
+
+#define BOOST_SPIRIT_TEST_HAMMER(r, data, elem) \
+ test::hammer<elem>(repeats);
+ /***/
+
+#define BOOST_SPIRIT_TEST_MEASURE(r, data, elem) \
+ test::report<elem>(BOOST_PP_STRINGIZE(elem), repeats); \
+ /***/
+
+#define BOOST_SPIRIT_TEST_BENCHMARK(max_repeats, FSeq) \
+ long repeats = 100; \
+ double measured = 0; \
+ while (measured < 2.0 && repeats <= max_repeats) \
+ { \
+ repeats *= 10; \
+ util::high_resolution_timer time; \
+ BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_TEST_HAMMER, _, FSeq) \
+ measured = time.elapsed(); \
+ } \
+ BOOST_PP_SEQ_FOR_EACH(BOOST_SPIRIT_TEST_MEASURE, _, FSeq) \
+ /***/
+}
+
+#endif
diff --git a/src/boost/libs/spirit/workbench/qi/Jamfile b/src/boost/libs/spirit/workbench/qi/Jamfile
new file mode 100644
index 00000000..176c28cb
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/Jamfile
@@ -0,0 +1,19 @@
+#==============================================================================
+# Copyright (c) 2001-2010 Joel de Guzman
+# Copyright (c) 2001-2010 Hartmut Kaiser
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+project spirit-qi-benchmark
+ : requirements
+ <include>.
+ <c++-template-depth>300
+ :
+ :
+ ;
+# performance tests
+exe int_parser : int_parser.cpp ;
+exe real_parser : real_parser.cpp ;
+exe attr_vs_actions : attr_vs_actions.cpp ;
+exe keywords : keywords.cpp ;
diff --git a/src/boost/libs/spirit/workbench/qi/attr_vs_actions.cpp b/src/boost/libs/spirit/workbench/qi/attr_vs_actions.cpp
new file mode 100644
index 00000000..d85e0f48
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/attr_vs_actions.cpp
@@ -0,0 +1,98 @@
+// Copyright (c) 2002-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+using boost::spirit::qi::grammar;
+using boost::spirit::qi::rule;
+using boost::spirit::qi::char_;
+using boost::spirit::qi::parse;
+using boost::spirit::qi::_val;
+using boost::spirit::qi::_1;
+using boost::phoenix::push_back;
+
+#define ATTR_PROPAGATE
+
+struct test_attr
+{
+ test_attr()
+ {
+ std::cout << "default construct" << std::endl;
+ }
+
+ test_attr(char)
+ {
+ std::cout << "construct from char" << std::endl;
+ }
+
+ test_attr(test_attr const&)
+ {
+ std::cout << "copy construct" << std::endl;
+ }
+
+ test_attr& operator=(test_attr const&)
+ {
+ std::cout << "assign" << std::endl;
+ return *this;
+ }
+};
+
+template <typename Iterator>
+struct test_parser : grammar<Iterator, std::vector<test_attr>() >
+{
+ test_parser() : test_parser::base_type(start)
+ {
+#ifdef ATTR_PROPAGATE
+ start = char_ >> *(',' >> char_);
+#else
+ start = char_[push_back(_val, _1)] >> *(',' >> char_[push_back(_val, _1)]);
+#endif
+ }
+
+ rule<Iterator, std::vector<test_attr>()> start;
+};
+
+int main()
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef test_parser<iterator_type> test_parser;
+
+ test_parser g;
+ std::string str = "a,b,c,d,e";
+
+ std::vector<test_attr> result;
+ result.reserve(20);
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = parse(iter, end, g, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/qi/int_parser.cpp b/src/boost/libs/spirit/workbench/qi/int_parser.cpp
new file mode 100644
index 00000000..3a25cd3a
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/int_parser.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#include "../measure.hpp"
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <boost/spirit/include/qi.hpp>
+
+namespace
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Generate a random number string with N digits
+ std::string
+ gen_int(int digits)
+ {
+ std::string result;
+ if (rand()%2) // Prepend a '-'
+ result += '-';
+ result += '1' + (rand()%9); // The first digit cannot be '0'
+
+ for (int i = 1; i < digits; ++i) // Generate the remaining digits
+ result += '0' + (rand()%10);
+ return result;
+ }
+
+ std::string numbers[9];
+ char const* first[9];
+ char const* last[9];
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct atoi_test : test::base
+ {
+ void benchmark()
+ {
+ for (int i = 0; i < 9; ++i)
+ this->val += atoi(first[i]);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct strtol_test : test::base
+ {
+ void benchmark()
+ {
+ for (int i = 0; i < 9; ++i)
+ this->val += strtol(first[i], const_cast<char**>(&last[i]), 10);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct spirit_int_test : test::base
+ {
+ static int parse(char const* first, char const* last)
+ {
+ int n;
+ namespace qi = boost::spirit::qi;
+ using qi::int_;
+ qi::parse(first, last, int_, n);
+ return n;
+ }
+
+ void benchmark()
+ {
+ for (int i = 0; i < 9; ++i)
+ this->val += parse(first[i], last[i]);
+ }
+ };
+}
+
+int main()
+{
+ // Seed the random generator
+ srand(time(0));
+
+ // Generate random integers with 1 .. 9 digits
+ // We test only 9 digits to avoid overflow
+ std::cout << "///////////////////////////////////////////////////////////////////////////" << std::endl;
+ std::cout << "Numbers to test:" << std::endl;
+ for (int i = 0; i < 9; ++i)
+ {
+ numbers[i] = gen_int(i+1);
+ first[i] = numbers[i].c_str();
+ last[i] = first[i];
+ while (*last[i])
+ last[i]++;
+ std::cout << i+1 << " digit number:" << numbers[i] << std::endl;
+ }
+ std::cout << "///////////////////////////////////////////////////////////////////////////" << std::endl;
+
+ BOOST_SPIRIT_TEST_BENCHMARK(
+ 10000000, // This is the maximum repetitions to execute
+ (atoi_test)
+ (strtol_test)
+ (spirit_int_test)
+ )
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/qi/keywords.cpp b/src/boost/libs/spirit/workbench/qi/keywords.cpp
new file mode 100644
index 00000000..d8f7f450
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/keywords.cpp
@@ -0,0 +1,553 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2011 Thomas Bernard
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#define FUSION_MAX_VECTOR_SIZE 50
+#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#define BOOST_MPL_LIMIT_LIST_SIZE 50
+#define BOOST_MPL_LIMIT_VECTOR_SIZE 50
+
+#include "../measure.hpp"
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/spirit/include/qi_permutation.hpp>
+#include <boost/spirit/home/qi/string/tst_map.hpp>
+#include <boost/spirit/repository/include/qi_kwd.hpp>
+#include <boost/spirit/repository/include/qi_keywords.hpp>
+#include <boost/optional.hpp>
+#include <boost/spirit/home/phoenix/core/argument.hpp>
+#include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+#include <vector>
+#include <iterator>
+#include <stdexcept>
+
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/seq/for_each_i.hpp>
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#define KEYS_5
+
+#include "keywords.hpp"
+
+#define declOptions(r, data, i, elem) boost::optional<int> BOOST_PP_CAT(option,i);
+#define fusionOptions(r, data, i, elem) (boost::optional<int>, BOOST_PP_CAT(option,i))
+
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our parsedData struct
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_parsedData_struct
+ struct parsedDataOptions
+ {
+ BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
+ };
+ struct parsedData
+ {
+
+ std::string name;
+ parsedDataOptions options;
+ void clear()
+ {
+ name.clear();
+ }
+ };
+
+ struct parsedData2
+ {
+ std::string name;
+ BOOST_PP_SEQ_FOR_EACH_I(declOptions,_,keys)
+
+ void clear()
+ {
+ name.clear();
+ }
+ };
+}
+
+std::ostream &operator<<(std::ostream & os, client::parsedData &data)
+{
+ os << data.name <<std::endl;
+
+#define generateOutput1(r, d, i, elem) if( BOOST_PP_CAT(data.options.option, i) ) os<< BOOST_PP_STRINGIZE( BOOST_PP_CAT(option,i)) <<" "<< * BOOST_PP_CAT(data.options.option , i)<<std::endl;
+ BOOST_PP_SEQ_FOR_EACH_I(generateOutput1,_,keys)
+
+ os<<std::endl;
+
+ return os;
+}
+
+std::ostream &operator<<(std::ostream & os, client::parsedData2 &data)
+{
+ os << data.name <<std::endl;
+
+#define generateOutput2(r, d, i, elem) if(BOOST_PP_CAT(data.option, i)) os<< BOOST_PP_STRINGIZE( BOOST_PP_CAT(option,i)) <<" "<< * BOOST_PP_CAT(data.option,i)<<std::endl;
+ BOOST_PP_SEQ_FOR_EACH_I(generateOutput2,_,keys)
+
+ os<<std::endl;
+
+ return os;
+}
+
+
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::parsedDataOptions,
+ BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
+ )
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::parsedData,
+ (std::string, name)
+ (client::parsedDataOptions, options)
+ )
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::parsedData2,
+ (std::string, name)
+ BOOST_PP_SEQ_FOR_EACH_I(fusionOptions,_,keys)
+ )
+enum variation
+{
+ full,
+ no_assign,
+ assign
+};
+namespace client
+{
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our parsedData parser
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_parsedData_parser
+ template <typename Iterator>
+ struct permutation_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
+ {
+ permutation_parser() : permutation_parser::base_type(start)
+ {
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+ using boost::phoenix::at_c;
+ using boost::phoenix::assign;
+ using qi::_r1;
+ using qi::_1;
+ using qi::_val;
+ using qi::omit;
+ using qi::repeat;
+
+
+ quoted_string %= lexeme[+(char_-' ')];
+
+#define generateOptions1(r, data, i, elem) BOOST_PP_IF(i, ^(lit(elem) > int_) , (lit(elem) > int_))
+ options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions1,_,keys));
+
+ start %=
+ quoted_string
+ >> options;
+ ;
+ v_vals = repeat(1,2)[int_];
+ }
+
+ typedef parsedData parser_target_type;
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
+ qi::rule<Iterator, std::vector<int>(), ascii::space_type> v_vals;
+
+ qi::rule<Iterator, parsedData(), ascii::space_type> start;
+ };
+
+ template <typename Iterator>
+ struct alternative_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
+ {
+ alternative_parser() : alternative_parser::base_type(start)
+ {
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+ using boost::phoenix::at_c;
+ using qi::_r1;
+ using qi::_1;
+ using qi::_val;
+
+ quoted_string %= lexeme[+(char_-' ')];
+
+#define generateOptions2(r, data, i, elem) BOOST_PP_IF(i, |(lit(elem) > int_[at_c<i+1>(_r1)=_1]) , (lit(elem) > int_[at_c<i+1>(_r1)=_1]))
+ options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions2,_,keys));
+
+ start =
+ quoted_string [at_c<0>(_val)=_1]
+ >> *options(_val);
+ ;
+ }
+
+ typedef parsedData2 parser_target_type;
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ qi::rule<Iterator, void(parsedData2 & ), ascii::space_type> options;
+ qi::rule<Iterator, parsedData2(), ascii::space_type> start;
+ };
+
+
+
+ template <typename Iterator,typename variation>
+ struct tst_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
+ {
+ typedef variation variation_type;
+
+ tst_parser() : tst_parser::base_type(startalias)
+ {
+ namespace phx = boost::phoenix;
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+ using boost::phoenix::at_c;
+ using qi::_r1;
+ using qi::_1;
+ using qi::_a;
+ using qi::_val;
+ using qi::locals;
+ using qi::parameterized_nonterminal;
+
+ startalias = start.alias();
+ quoted_string %= lexeme[+(char_-' ')];
+
+#define generateRules(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
+ BOOST_PP_SEQ_FOR_EACH_I(generateRules,_,keys)
+
+#define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
+
+
+ options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
+ switch(variation_type::value)
+ {
+ case full:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options [_a=_1] >> lazy(*_a));
+ ;
+ break;
+ }
+ case no_assign:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options >> int_);
+ ;
+ break;
+ }
+ case assign:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options [_a=_1] >> int_);
+ ;
+ break;
+ }
+ }
+
+
+ }
+
+ parsedData2 *currentObj;
+
+ typedef parsedData2 parser_target_type;
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ typedef qi::rule<Iterator, ascii::space_type> optionsRule;
+#define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
+
+ BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
+
+ qi::symbols<char,optionsRule* > options;
+ qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
+ qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
+ };
+
+
+
+ template <typename Iterator,typename variation>
+ struct tst_map_parser : qi::grammar<Iterator, parsedData2(), ascii::space_type>
+ {
+ typedef variation variation_type;
+ tst_map_parser() : tst_map_parser::base_type(startalias)
+ {
+ namespace phx = boost::phoenix;
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+ using boost::phoenix::at_c;
+ using qi::_r1;
+ using qi::_1;
+ using qi::_a;
+ using qi::_val;
+ using qi::locals;
+ using qi::parameterized_nonterminal;
+
+ startalias = start.alias();
+ quoted_string %= lexeme[+(char_-' ')];
+
+#define generateRules3(r, data, i, elem) BOOST_PP_CAT(rule,i) = int_[phx::at_c<i+1>(*phx::ref(currentObj))=_1];
+ BOOST_PP_SEQ_FOR_EACH_I(generateRules3,_,keys)
+
+#define generateOptions3(r, data, i, elem) (elem,& BOOST_PP_CAT(rule,i))
+
+
+ options.add BOOST_PP_SEQ_FOR_EACH_I(generateOptions3,_,keys);
+
+ switch(variation_type::value)
+ {
+ case full:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options [_a=_1] >> lazy(*_a));
+ ;
+ break;
+ }
+ case no_assign:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options >> int_);
+ ;
+ break;
+ }
+ case assign:
+ {
+ start =
+ quoted_string [at_c<0>(_val)=_1][phx::ref(currentObj)=&_val]
+ >> *( options [_a=_1] >> int_);
+ ;
+ break;
+ }
+ }
+ }
+
+ parsedData2 *currentObj;
+
+ typedef parsedData2 parser_target_type;
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ typedef qi::rule<Iterator, ascii::space_type> optionsRule;
+#define declareRules(r, data, i, elem) optionsRule BOOST_PP_CAT(rule,i);
+
+ BOOST_PP_SEQ_FOR_EACH_I(declareRules,_,keys)
+
+ qi::symbols<char,optionsRule*, boost::spirit::qi::tst_map<char,optionsRule*> > options;
+ qi::rule<Iterator, parsedData2(), ascii::space_type> startalias;
+ qi::rule<Iterator, parsedData2(), qi::locals<optionsRule*>, ascii::space_type> start;
+ };
+
+
+ template <typename Iterator>
+ struct kwd_parser : qi::grammar<Iterator, parsedData(), ascii::space_type>
+ {
+ kwd_parser() : kwd_parser::base_type(start)
+ {
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+ using qi::_r1;
+ using qi::_1;
+ using qi::_val;
+ using boost::spirit::repository::qi::kwd;
+
+ quoted_string %= lexeme[+(char_-' ')];
+
+#define generateOptions4(r, data, i, elem) BOOST_PP_IF(i, / kwd( elem )[ int_ ] , kwd( elem )[ int_ ] )
+ options = (BOOST_PP_SEQ_FOR_EACH_I(generateOptions4,_,keys));
+
+ start %=
+ quoted_string
+ >> options;
+ ;
+ }
+
+ typedef parsedData parser_target_type;
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ qi::rule<Iterator, parsedDataOptions(), ascii::space_type> options;
+ qi::rule<Iterator, boost::fusion::vector<boost::optional<int>,boost::optional<int> > () , ascii::space_type> v_vals;
+
+ qi::rule<Iterator, parsedData(), ascii::space_type> start;
+ };
+
+}
+
+
+template <typename parserType>
+ struct timeParser : test::base{
+ timeParser(const std::string & str) : str(str)
+ {
+ }
+ parserType &get_parser(){
+ static parserType parser;
+ return parser;
+ }
+
+ std::string str;
+
+ void benchmark()
+ {
+
+ using boost::spirit::ascii::space;
+ bool r = false;
+ std::string::const_iterator end = str.end();
+ std::string::const_iterator iter = str.begin();
+
+
+ typename parserType::parser_target_type data;
+ r = phrase_parse(iter, end, get_parser(), space, data);
+
+ if (r && iter == end)
+ {
+ this->val += data.name.size();
+ }
+ else
+ {
+ throw std::runtime_error("Parsing failed");
+ }
+ }
+
+ };
+
+
+
+
+typedef std::string::const_iterator iterator_type;
+typedef client::permutation_parser<iterator_type> permutation_parser;
+typedef client::kwd_parser<iterator_type> kwd_parser;
+typedef client::alternative_parser<iterator_type> alternative_parser;
+typedef client::tst_map_parser<iterator_type, boost::mpl::int_<full> > tst_map_parser;
+
+struct permutation_timer_fwd : timeParser<permutation_parser>
+{
+ permutation_timer_fwd() : timeParser<permutation_parser>(fwd) {}
+};
+
+struct permutation_timer_back : timeParser<permutation_parser>
+{
+ permutation_timer_back() : timeParser<permutation_parser>(back) {}
+};
+
+struct alternative_timer_fwd : timeParser<alternative_parser>
+{
+ alternative_timer_fwd() : timeParser<alternative_parser>(fwd) {}
+};
+
+struct alternative_timer_back : timeParser<alternative_parser>
+{
+ alternative_timer_back() : timeParser<alternative_parser>(back) {}
+};
+
+struct tst_timer_fwd_full : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >
+{
+ tst_timer_fwd_full() : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<full> > >(fwd) {}
+};
+
+struct tst_timer_fwd_no_assign : timeParser< client::tst_parser<iterator_type, boost::mpl::int_<no_assign> > >
+{
+ tst_timer_fwd_no_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<no_assign> > >(fwd) {}
+};
+
+struct tst_timer_fwd_assign : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >
+{
+ tst_timer_fwd_assign() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<assign> > >(fwd) {}
+};
+
+
+
+struct tst_timer_back : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >
+{
+ tst_timer_back() : timeParser< client::tst_parser<iterator_type,boost::mpl::int_<full> > >(back) {}
+};
+
+struct tst_map_timer_fwd : timeParser<tst_map_parser>
+{
+ tst_map_timer_fwd() : timeParser<tst_map_parser>(fwd) {}
+};
+
+struct tst_map_timer_back : timeParser<tst_map_parser>
+{
+ tst_map_timer_back() : timeParser<tst_map_parser>(back) {}
+};
+
+struct kwd_timer_fwd : timeParser<kwd_parser>
+{
+ kwd_timer_fwd() : timeParser<kwd_parser>(fwd) {}
+};
+
+struct kwd_timer_back : timeParser<kwd_parser>
+{
+ kwd_timer_back() : timeParser<kwd_parser>(back) {}
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+ int
+main()
+{
+
+ BOOST_SPIRIT_TEST_BENCHMARK(
+ 10000000000, // This is the maximum repetitions to execute
+ (permutation_timer_fwd)
+ (permutation_timer_back)
+ (alternative_timer_fwd)
+ (alternative_timer_back)
+ (tst_timer_fwd_full)
+ (tst_timer_fwd_no_assign)
+ (tst_timer_fwd_assign)
+ (tst_timer_back)
+ (tst_map_timer_fwd)
+ (tst_map_timer_back)
+ (kwd_timer_fwd)
+ (kwd_timer_back)
+ )
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
+}
+
+
diff --git a/src/boost/libs/spirit/workbench/qi/keywords.hpp b/src/boost/libs/spirit/workbench/qi/keywords.hpp
new file mode 100644
index 00000000..b57adc26
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/keywords.hpp
@@ -0,0 +1,49 @@
+/*=============================================================================
+ Copyright (c) 2011 Thomas Bernard
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#if defined(KEYS_1)
+#define keys ("WeaBGNogxKwkyFilMHOp")
+
+const std::string fwd = "test WeaBGNogxKwkyFilMHOp 1655 ";
+const std::string back = "test WeaBGNogxKwkyFilMHOp 1372 ";
+#endif
+#if defined(KEYS_5)
+#define keys ("xSjJfIbmYDvQHhKTLZca")("JPvLQbGsXantCZpoeEiB")("MAZjzUrtdRSmhNnqxPVX")("PhuXTxIQCijHnZgUkLMY")("yQbTUMoPqwKvpIzekhfY")
+
+const std::string fwd = "test xSjJfIbmYDvQHhKTLZca 1450 JPvLQbGsXantCZpoeEiB 1691 MAZjzUrtdRSmhNnqxPVX 64 PhuXTxIQCijHnZgUkLMY 640 yQbTUMoPqwKvpIzekhfY 135";
+const std::string back = "test yQbTUMoPqwKvpIzekhfY 1903 PhuXTxIQCijHnZgUkLMY 404 MAZjzUrtdRSmhNnqxPVX 1473 JPvLQbGsXantCZpoeEiB 1478 xSjJfIbmYDvQHhKTLZca 1063";
+#endif
+#if defined(KEYS_10)
+#define keys ("briLcUzOEDAswdGuIXlp")("ZwKsyzktMrnERbDLThlB")("QCvkgGRYrmDVfiApzStM")("FUsjQAtlVrYSBmLvzxid")("gcvoqwKZIGMxatCdkDLH")("zmoqaLnEjGstTIbDkhBe")("cMQikmaJZgfEDIeNYGxK")("dufrWGRjHqZOENKhJitl")("MJKlZWrFVBLoUfjDcREw")("yVaJUIlYvumSdpTEXhKB")
+
+const std::string fwd = "test briLcUzOEDAswdGuIXlp 1580 ZwKsyzktMrnERbDLThlB 301 QCvkgGRYrmDVfiApzStM 301 FUsjQAtlVrYSBmLvzxid 1050 gcvoqwKZIGMxatCdkDLH 229 zmoqaLnEjGstTIbDkhBe 1962 cMQikmaJZgfEDIeNYGxK 789 dufrWGRjHqZOENKhJitl 1991 MJKlZWrFVBLoUfjDcREw 1819 yVaJUIlYvumSdpTEXhKB 193 ";
+const std::string back = "test yVaJUIlYvumSdpTEXhKB 1009 MJKlZWrFVBLoUfjDcREw 1585 dufrWGRjHqZOENKhJitl 313 cMQikmaJZgfEDIeNYGxK 791 zmoqaLnEjGstTIbDkhBe 544 gcvoqwKZIGMxatCdkDLH 672 FUsjQAtlVrYSBmLvzxid 78 QCvkgGRYrmDVfiApzStM 1069 ZwKsyzktMrnERbDLThlB 1741 briLcUzOEDAswdGuIXlp 1051 ";
+#endif
+#if defined(KEYS_20)
+#define keys ("yTMiuczAoDwJhIBCGvPl")("JUTVaEqDepvsiXwBgSYd")("voeXaAjyCqKtFxRhEblz")("rvQaNuXGkILPcdnSbWKw")("DWrTLiQlHhIjCXVEgGtw")("OMjiwLbahJdCzUGNmoZX")("FDNwcClbuBHeShriUfMK")("FkXLDcdKfJmjtgpAvVSG")("gjQWltFPcdvkBOnEbpGr")("MHkicpLbzqOFUVgnrQZG")("RPLWdKwJZAgsmFeqXnNx")("mdRMYcEfbezLguxOXBhF")("QsiEYSpTjonBqHLUaWzD")("POZcyDElsqoJGmSpQXrw")("PlscizNMqaYvLZBTxtQA")("zhxamRtXHuoyriGJjSIn")("YDAuwLaZEnNGgIJCUepR")("ogOdBYzCEJZqMHmuRsPt")("gWFzoLBUheNwlVrcOYbT")("pKcMQIkvriCLxfSDNEXA")
+
+const std::string fwd = "test yTMiuczAoDwJhIBCGvPl 1021 JUTVaEqDepvsiXwBgSYd 1480 voeXaAjyCqKtFxRhEblz 255 rvQaNuXGkILPcdnSbWKw 1792 DWrTLiQlHhIjCXVEgGtw 1117 OMjiwLbahJdCzUGNmoZX 920 FDNwcClbuBHeShriUfMK 924 FkXLDcdKfJmjtgpAvVSG 1798 gjQWltFPcdvkBOnEbpGr 1298 MHkicpLbzqOFUVgnrQZG 673 RPLWdKwJZAgsmFeqXnNx 35 mdRMYcEfbezLguxOXBhF 703 QsiEYSpTjonBqHLUaWzD 595 POZcyDElsqoJGmSpQXrw 798 PlscizNMqaYvLZBTxtQA 780 zhxamRtXHuoyriGJjSIn 385 YDAuwLaZEnNGgIJCUepR 1834 ogOdBYzCEJZqMHmuRsPt 43 gWFzoLBUheNwlVrcOYbT 1885 pKcMQIkvriCLxfSDNEXA 1397 ";
+const std::string back = "test pKcMQIkvriCLxfSDNEXA 1885 gWFzoLBUheNwlVrcOYbT 978 ogOdBYzCEJZqMHmuRsPt 929 YDAuwLaZEnNGgIJCUepR 1929 zhxamRtXHuoyriGJjSIn 859 PlscizNMqaYvLZBTxtQA 1505 POZcyDElsqoJGmSpQXrw 1317 QsiEYSpTjonBqHLUaWzD 122 mdRMYcEfbezLguxOXBhF 610 RPLWdKwJZAgsmFeqXnNx 133 MHkicpLbzqOFUVgnrQZG 371 gjQWltFPcdvkBOnEbpGr 1770 FkXLDcdKfJmjtgpAvVSG 128 FDNwcClbuBHeShriUfMK 1829 OMjiwLbahJdCzUGNmoZX 1187 DWrTLiQlHhIjCXVEgGtw 822 rvQaNuXGkILPcdnSbWKw 1321 voeXaAjyCqKtFxRhEblz 855 JUTVaEqDepvsiXwBgSYd 219 yTMiuczAoDwJhIBCGvPl 1209 ";
+#endif
+#if defined(KEYS_30)
+#define keys ("GgrRUxIZCFYkpnsvyzwb")("fLpJmgZEQAKdbcSuNFPr")("aMZVkzfvrXLyPjeUBRus")("gBefvhWdnzbEGHLmUDpO")("fXZnwLWDeNtrMQzhqOsb")("CusxSlJpKvtmOHrBjzAX")("yufeisPwaUIKtNYVTAbC")("WMCzLygdkDHAOEpJeSBr")("lxQzaLBHwTvXJZUMyVho")("JdPxVYOgsGUEFBtvmZkL")("wPaFKqnJRfuODGWLvkgA")("iwJpIslCdTqEnMQocbxN")("vRQzSrpTMCKhwABHLPDx")("xHAJatdSfnXevMYKwLcV")("mEDZwUnfxzAaqkpQlNKr")("rHQwgpxqPsWzJGVlYEMn")("vczEywanJWBrMHIhLDKx")("rWpuIPmoReFSBGNYLUXJ")("cHNZVmYAOpkBRwWUhyae")("tNOpTMRadcHjLDUAoyvX")("bRLrhnmXvdyTZcHWQgDB")("STpWfPAhqQvjsdkHeZlU")("JsMdBawTzIgPGouHipRl")("qEHdLhXwsmSfbaoWkGiM")("jrZHNnElwcPAbsOFzdfT")("NvarfYcMCUXqxbDwgRVT")("zwOxryohHjCuNpnKDPdl")("mHOtuLrZKveTjsbzApan")("qFEHhLbeWpUtaozKCBSX")("pnlSjeQETKfRwNvOYDdJ")
+
+const std::string fwd = "test GgrRUxIZCFYkpnsvyzwb 573 fLpJmgZEQAKdbcSuNFPr 1748 aMZVkzfvrXLyPjeUBRus 919 gBefvhWdnzbEGHLmUDpO 1491 fXZnwLWDeNtrMQzhqOsb 1023 CusxSlJpKvtmOHrBjzAX 656 yufeisPwaUIKtNYVTAbC 1963 WMCzLygdkDHAOEpJeSBr 1171 lxQzaLBHwTvXJZUMyVho 51 JdPxVYOgsGUEFBtvmZkL 125 wPaFKqnJRfuODGWLvkgA 273 iwJpIslCdTqEnMQocbxN 58 vRQzSrpTMCKhwABHLPDx 347 xHAJatdSfnXevMYKwLcV 440 mEDZwUnfxzAaqkpQlNKr 442 rHQwgpxqPsWzJGVlYEMn 1527 vczEywanJWBrMHIhLDKx 1671 rWpuIPmoReFSBGNYLUXJ 457 cHNZVmYAOpkBRwWUhyae 1721 tNOpTMRadcHjLDUAoyvX 919 bRLrhnmXvdyTZcHWQgDB 317 STpWfPAhqQvjsdkHeZlU 1886 JsMdBawTzIgPGouHipRl 352 qEHdLhXwsmSfbaoWkGiM 1641 jrZHNnElwcPAbsOFzdfT 1430 NvarfYcMCUXqxbDwgRVT 383 zwOxryohHjCuNpnKDPdl 402 mHOtuLrZKveTjsbzApan 46 qFEHhLbeWpUtaozKCBSX 681 pnlSjeQETKfRwNvOYDdJ 36 ";
+const std::string back = "test pnlSjeQETKfRwNvOYDdJ 976 qFEHhLbeWpUtaozKCBSX 1787 mHOtuLrZKveTjsbzApan 832 zwOxryohHjCuNpnKDPdl 487 NvarfYcMCUXqxbDwgRVT 1973 jrZHNnElwcPAbsOFzdfT 68 qEHdLhXwsmSfbaoWkGiM 157 JsMdBawTzIgPGouHipRl 1017 STpWfPAhqQvjsdkHeZlU 74 bRLrhnmXvdyTZcHWQgDB 1010 tNOpTMRadcHjLDUAoyvX 313 cHNZVmYAOpkBRwWUhyae 521 rWpuIPmoReFSBGNYLUXJ 1286 vczEywanJWBrMHIhLDKx 1942 rHQwgpxqPsWzJGVlYEMn 1048 mEDZwUnfxzAaqkpQlNKr 1170 xHAJatdSfnXevMYKwLcV 152 vRQzSrpTMCKhwABHLPDx 1330 iwJpIslCdTqEnMQocbxN 1927 wPaFKqnJRfuODGWLvkgA 1347 JdPxVYOgsGUEFBtvmZkL 1569 lxQzaLBHwTvXJZUMyVho 766 WMCzLygdkDHAOEpJeSBr 966 yufeisPwaUIKtNYVTAbC 186 CusxSlJpKvtmOHrBjzAX 1494 fXZnwLWDeNtrMQzhqOsb 1722 gBefvhWdnzbEGHLmUDpO 1829 aMZVkzfvrXLyPjeUBRus 134 fLpJmgZEQAKdbcSuNFPr 963 GgrRUxIZCFYkpnsvyzwb 465 ";
+#endif
+#if defined(KEYS_40)
+#define keys ("xjSUvfTWlVeoLEtdmKBz")("HSDfyWRmjsxiXFOJQvoT")("gvByQMLTjeGdiVXkWqnf")("HZJdriPpDLsvEhfzKXBa")("hMXgUkzBHRbJWvCalsAN")("rOsvXRwgNyTkPDYBzELC")("CbRfwqJONDHFYGzPaZpo")("dUOPAuIDElRjWQeBkiMN")("KTWfmbAeOUhJsuaEvMwr")("QhglZMDOsAYwamrxvPUH")("TNgnvqHzjFyDPlhmVItC")("RxOnIzgaMdpwekBYNvLC")("VnPsKoruveyOUDQtBRGj")("QJcuxWkrsgfviopSDIhC")("ZAhUFndDgemHLTtsCfpu")("HQywNcbTtzpknSsBjJqo")("fCKXUHGBPzkZlTYoSnWy")("FagwxrUtbGizkNcTELfC")("kNvJBuTQZbEfWVYLlrOA")("pHDuhFJBOrzPALCtEWNU")("FczoOhKDLyNgGdfPrUJj")("DPzioljtskSICqveWrxm")("LhbOFicHYwCpdUqJaVgW")("rbVRhimjwDLlvSIFWUxt")("xsUXlLEyVQinuSZjbwGD")("zAGgCYZqhVMkfWavsKeX")("zetXFOmPBZRQJswHYDbj")("ZvwSjyIJBmQRNiVTDpqE")("cixUqrmszRbvpMPhTwVt")("mEeHfzKtrSyUDGcnOlgv")("oqYWiUSKmdJGXBNnlEue")("cTkYIdoQpHbnDhuCywJi")("kGNHjfpBlntPFwygicIL")("PFSwazNXjbGrdAuRKqVk")("drwmptOPlUxgnCjyqWSJ")("CBLImQsdlkXqEfDWpYug")("DHgsPldqzuGxfEnLFriS")("ATRzQeVUgIJuCmcqSPGX")("WiPZTDXgxeAsKFwfamoy")("KgdSxtYMlEqmPJkFRzWQ")
+
+const std::string fwd = "test xjSUvfTWlVeoLEtdmKBz 1324 HSDfyWRmjsxiXFOJQvoT 310 gvByQMLTjeGdiVXkWqnf 671 HZJdriPpDLsvEhfzKXBa 427 hMXgUkzBHRbJWvCalsAN 524 rOsvXRwgNyTkPDYBzELC 1295 CbRfwqJONDHFYGzPaZpo 1233 dUOPAuIDElRjWQeBkiMN 1432 KTWfmbAeOUhJsuaEvMwr 623 QhglZMDOsAYwamrxvPUH 70 TNgnvqHzjFyDPlhmVItC 235 RxOnIzgaMdpwekBYNvLC 170 VnPsKoruveyOUDQtBRGj 918 QJcuxWkrsgfviopSDIhC 619 ZAhUFndDgemHLTtsCfpu 27 HQywNcbTtzpknSsBjJqo 985 fCKXUHGBPzkZlTYoSnWy 1876 FagwxrUtbGizkNcTELfC 1761 kNvJBuTQZbEfWVYLlrOA 1823 pHDuhFJBOrzPALCtEWNU 1872 FczoOhKDLyNgGdfPrUJj 162 DPzioljtskSICqveWrxm 1704 LhbOFicHYwCpdUqJaVgW 405 rbVRhimjwDLlvSIFWUxt 135 xsUXlLEyVQinuSZjbwGD 1555 zAGgCYZqhVMkfWavsKeX 1553 zetXFOmPBZRQJswHYDbj 315 ZvwSjyIJBmQRNiVTDpqE 1844 cixUqrmszRbvpMPhTwVt 949 mEeHfzKtrSyUDGcnOlgv 1293 oqYWiUSKmdJGXBNnlEue 1554 cTkYIdoQpHbnDhuCywJi 1829 kGNHjfpBlntPFwygicIL 191 PFSwazNXjbGrdAuRKqVk 355 drwmptOPlUxgnCjyqWSJ 1403 CBLImQsdlkXqEfDWpYug 57 DHgsPldqzuGxfEnLFriS 748 ATRzQeVUgIJuCmcqSPGX 841 WiPZTDXgxeAsKFwfamoy 1660 KgdSxtYMlEqmPJkFRzWQ 1126 ";
+const std::string back = "test KgdSxtYMlEqmPJkFRzWQ 364 WiPZTDXgxeAsKFwfamoy 176 ATRzQeVUgIJuCmcqSPGX 793 DHgsPldqzuGxfEnLFriS 179 CBLImQsdlkXqEfDWpYug 1570 drwmptOPlUxgnCjyqWSJ 1635 PFSwazNXjbGrdAuRKqVk 793 kGNHjfpBlntPFwygicIL 1294 cTkYIdoQpHbnDhuCywJi 966 oqYWiUSKmdJGXBNnlEue 642 mEeHfzKtrSyUDGcnOlgv 830 cixUqrmszRbvpMPhTwVt 1842 ZvwSjyIJBmQRNiVTDpqE 1617 zetXFOmPBZRQJswHYDbj 718 zAGgCYZqhVMkfWavsKeX 587 xsUXlLEyVQinuSZjbwGD 1597 rbVRhimjwDLlvSIFWUxt 770 LhbOFicHYwCpdUqJaVgW 1100 DPzioljtskSICqveWrxm 473 FczoOhKDLyNgGdfPrUJj 74 pHDuhFJBOrzPALCtEWNU 902 kNvJBuTQZbEfWVYLlrOA 749 FagwxrUtbGizkNcTELfC 964 fCKXUHGBPzkZlTYoSnWy 819 HQywNcbTtzpknSsBjJqo 1535 ZAhUFndDgemHLTtsCfpu 859 QJcuxWkrsgfviopSDIhC 1648 VnPsKoruveyOUDQtBRGj 1368 RxOnIzgaMdpwekBYNvLC 757 TNgnvqHzjFyDPlhmVItC 245 QhglZMDOsAYwamrxvPUH 170 KTWfmbAeOUhJsuaEvMwr 671 dUOPAuIDElRjWQeBkiMN 1792 CbRfwqJONDHFYGzPaZpo 1117 rOsvXRwgNyTkPDYBzELC 1293 hMXgUkzBHRbJWvCalsAN 1563 HZJdriPpDLsvEhfzKXBa 675 gvByQMLTjeGdiVXkWqnf 1734 HSDfyWRmjsxiXFOJQvoT 1858 xjSUvfTWlVeoLEtdmKBz 1030 ";
+#endif
+#if defined(KEYS_50)
+#define keys ("QZMaswnqKlYGVWArzRSm")("EKWLSbqXhjIvQgpJrxnF")("ENVahOdugPMsewLIzGWD")("XeuQTSmbIFZcKvRJNOqP")("nOZjiVoQxeJhgRsPDFSI")("BNFEOLMKgepudtCmrPWR")("ElUzSiPTnCyvtdkeRxKL")("LwkRqhCYgpvjNEIVonWT")("ePqFoWSwgBkRcKvYxCsu")("uImFlasHEAPqzNtKWhTY")("LegKBDklPxyXhwUWMpTd")("wOLlVmQiKMrDdRxjSfcI")("wluBvdVhMazxSUWFCjtZ")("DuRnZmNdsOEeWrqxQFUz")("dQVlbzjCMNSwnRqrofFI")("ivdCbNxuXOWJBUGEjIwh")("gFzqlpbPCZtARScNrvjK")("PtGVUfkdiupEKsIOgjNW")("ucDVgUApjNkPGixQbdMS")("DwRyzVleMbBmOorvNTxX")("TYJjBKcZiFqpWyaLbNhS")("mgTbPuslkvFMrHVENcAY")("zDQxOBgJXswcWIqdMmZa")("jUbvKZIkrCduqtgMyAzx")("NlnChoIEKuXQdwzOvMat")("eNtPxwYzMJCDfsQVlLGA")("DhBpcTgvJtAROaLFMuwz")("QZXfGWqONEmHSytbUTnh")("yJHPXhVSpAwebWnkGxQZ")("UonOKFbImdWhuBspTcEg")("ytOAXPUDGrjgqeEvpTIs")("dEiSHXlCoAsfBhcwTNZJ")("QTtfvRhnVjZKdsOkFCzH")("vbFAtKSRYEskzBruWgXH")("sGLvhxcdbZJoujrwERDp")("QBvJhYMDsgGNfziSkPtF")("TWIfucYJrRQBPyKsFGzg")("sqhuViGvxDAkjLnfpmQC")("YHLhZVGXNOQrzKMFvRWk")("wykaZKTmfOoFHPQDAsqn")("lkzZeRXCHLaOjJDhsKtg")("CaWUzuhvkqHLrwBMbpFo")("STLfmxsWGEKRDyzadihv")("svpKlVfeGYjMEkCXbtDS")("GAJxeMwbWCDHiczpslVn")("aqDeBkoTOcrVPtliRzFH")("VvjJPaLxpuRKSDsdmtgY")("WHbLDZABtSFMElKJYPOj")("agKVtLdsSpPzTfOmNxWy")("ZIJokqupeBRrTlHNKChz")
+
+const std::string fwd = "test QZMaswnqKlYGVWArzRSm 1285 EKWLSbqXhjIvQgpJrxnF 966 ENVahOdugPMsewLIzGWD 1122 XeuQTSmbIFZcKvRJNOqP 1863 nOZjiVoQxeJhgRsPDFSI 1738 BNFEOLMKgepudtCmrPWR 842 ElUzSiPTnCyvtdkeRxKL 278 LwkRqhCYgpvjNEIVonWT 983 ePqFoWSwgBkRcKvYxCsu 1387 uImFlasHEAPqzNtKWhTY 282 LegKBDklPxyXhwUWMpTd 635 wOLlVmQiKMrDdRxjSfcI 563 wluBvdVhMazxSUWFCjtZ 1091 DuRnZmNdsOEeWrqxQFUz 1773 dQVlbzjCMNSwnRqrofFI 102 ivdCbNxuXOWJBUGEjIwh 1562 gFzqlpbPCZtARScNrvjK 354 PtGVUfkdiupEKsIOgjNW 1728 ucDVgUApjNkPGixQbdMS 1874 DwRyzVleMbBmOorvNTxX 1594 TYJjBKcZiFqpWyaLbNhS 1654 mgTbPuslkvFMrHVENcAY 89 zDQxOBgJXswcWIqdMmZa 1814 jUbvKZIkrCduqtgMyAzx 559 NlnChoIEKuXQdwzOvMat 748 eNtPxwYzMJCDfsQVlLGA 435 DhBpcTgvJtAROaLFMuwz 1649 QZXfGWqONEmHSytbUTnh 1530 yJHPXhVSpAwebWnkGxQZ 244 UonOKFbImdWhuBspTcEg 1712 ytOAXPUDGrjgqeEvpTIs 124 dEiSHXlCoAsfBhcwTNZJ 1759 QTtfvRhnVjZKdsOkFCzH 1655 vbFAtKSRYEskzBruWgXH 1325 sGLvhxcdbZJoujrwERDp 1979 QBvJhYMDsgGNfziSkPtF 304 TWIfucYJrRQBPyKsFGzg 1721 sqhuViGvxDAkjLnfpmQC 1693 YHLhZVGXNOQrzKMFvRWk 389 wykaZKTmfOoFHPQDAsqn 1592 lkzZeRXCHLaOjJDhsKtg 902 CaWUzuhvkqHLrwBMbpFo 374 STLfmxsWGEKRDyzadihv 1912 svpKlVfeGYjMEkCXbtDS 61 GAJxeMwbWCDHiczpslVn 1652 aqDeBkoTOcrVPtliRzFH 591 VvjJPaLxpuRKSDsdmtgY 1892 WHbLDZABtSFMElKJYPOj 756 agKVtLdsSpPzTfOmNxWy 1866 ZIJokqupeBRrTlHNKChz 1972 ";
+const std::string back = "test ZIJokqupeBRrTlHNKChz 277 agKVtLdsSpPzTfOmNxWy 424 WHbLDZABtSFMElKJYPOj 313 VvjJPaLxpuRKSDsdmtgY 1114 aqDeBkoTOcrVPtliRzFH 1458 GAJxeMwbWCDHiczpslVn 1248 svpKlVfeGYjMEkCXbtDS 225 STLfmxsWGEKRDyzadihv 1745 CaWUzuhvkqHLrwBMbpFo 629 lkzZeRXCHLaOjJDhsKtg 130 wykaZKTmfOoFHPQDAsqn 10 YHLhZVGXNOQrzKMFvRWk 1463 sqhuViGvxDAkjLnfpmQC 1319 TWIfucYJrRQBPyKsFGzg 1057 QBvJhYMDsgGNfziSkPtF 445 sGLvhxcdbZJoujrwERDp 313 vbFAtKSRYEskzBruWgXH 1758 QTtfvRhnVjZKdsOkFCzH 1190 dEiSHXlCoAsfBhcwTNZJ 1008 ytOAXPUDGrjgqeEvpTIs 916 UonOKFbImdWhuBspTcEg 1699 yJHPXhVSpAwebWnkGxQZ 840 QZXfGWqONEmHSytbUTnh 1041 DhBpcTgvJtAROaLFMuwz 699 eNtPxwYzMJCDfsQVlLGA 701 NlnChoIEKuXQdwzOvMat 21 jUbvKZIkrCduqtgMyAzx 1506 zDQxOBgJXswcWIqdMmZa 689 mgTbPuslkvFMrHVENcAY 1292 TYJjBKcZiFqpWyaLbNhS 1015 DwRyzVleMbBmOorvNTxX 1099 ucDVgUApjNkPGixQbdMS 1389 PtGVUfkdiupEKsIOgjNW 820 gFzqlpbPCZtARScNrvjK 1748 ivdCbNxuXOWJBUGEjIwh 240 dQVlbzjCMNSwnRqrofFI 546 DuRnZmNdsOEeWrqxQFUz 1015 wluBvdVhMazxSUWFCjtZ 1058 wOLlVmQiKMrDdRxjSfcI 935 LegKBDklPxyXhwUWMpTd 1609 uImFlasHEAPqzNtKWhTY 17 ePqFoWSwgBkRcKvYxCsu 680 LwkRqhCYgpvjNEIVonWT 189 ElUzSiPTnCyvtdkeRxKL 589 BNFEOLMKgepudtCmrPWR 622 nOZjiVoQxeJhgRsPDFSI 741 XeuQTSmbIFZcKvRJNOqP 1843 ENVahOdugPMsewLIzGWD 220 EKWLSbqXhjIvQgpJrxnF 774 QZMaswnqKlYGVWArzRSm 140 ";
+#endif
diff --git a/src/boost/libs/spirit/workbench/qi/real_parser.cpp b/src/boost/libs/spirit/workbench/qi/real_parser.cpp
new file mode 100644
index 00000000..66ae54e5
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/qi/real_parser.cpp
@@ -0,0 +1,118 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+#include "../measure.hpp"
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <boost/spirit/include/qi.hpp>
+
+namespace
+{
+ int const ndigits = 9;
+ std::string numbers[ndigits] =
+ {
+ "1234",
+ "-1.2e3",
+ "0.1",
+ "-1.2e-3",
+ "-.2e3",
+ "-2e6",
+ "1.2345e5",
+ "-5.7222349715140557e+307",
+ "2.0332938517515416e-308"
+ };
+
+ char const* first[ndigits];
+ char const* last[ndigits];
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct atof_test : test::base
+ {
+ void benchmark()
+ {
+ for (int i = 0; i < ndigits; ++i)
+ {
+ double d = atof(first[i]);
+ this->val += *reinterpret_cast<int*>(&d);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct strtod_test : test::base
+ {
+ void benchmark()
+ {
+ for (int i = 0; i < ndigits; ++i)
+ {
+ double d = strtod(first[i], const_cast<char**>(&last[i]));
+ this->val += *reinterpret_cast<int*>(&d);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ struct spirit_double_test : test::base
+ {
+ static double parse(char const* first, char const* last)
+ {
+ double n;
+ namespace qi = boost::spirit::qi;
+ using qi::double_;
+ qi::parse(first, last, double_, n);
+ return n;
+ }
+
+ void benchmark()
+ {
+ for (int i = 0; i < ndigits; ++i)
+ {
+ double d = parse(first[i], last[i]);
+ this->val += *reinterpret_cast<int*>(&d);
+ }
+ }
+ };
+}
+
+int main()
+{
+ std::cout << "///////////////////////////////////////////////////////////////////////////" << std::endl;
+ std::cout << "Numbers to test:" << std::endl;
+ for (int i = 0; i < ndigits; ++i)
+ {
+ first[i] = numbers[i].c_str();
+ last[i] = first[i];
+ while (*last[i])
+ last[i]++;
+ std::cout << numbers[i] << std::endl;
+ }
+ std::cout.precision(17);
+ std::cout << "///////////////////////////////////////////////////////////////////////////" << std::endl;
+ std::cout << "atof/strtod/qi.double results:" << std::endl;
+ for (int i = 0; i < ndigits; ++i)
+ {
+ std::cout
+ << atof(first[i]) << ','
+ << strtod(first[i], const_cast<char**>(&last[i])) << ','
+ << spirit_double_test::parse(first[i], last[i]) << ','
+ << std::endl;
+ }
+ std::cout << "///////////////////////////////////////////////////////////////////////////" << std::endl;
+
+ BOOST_SPIRIT_TEST_BENCHMARK(
+ 10000000, // This is the maximum repetitions to execute
+ (atof_test)
+ (strtod_test)
+ (spirit_double_test)
+ )
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
+}
+
diff --git a/src/boost/libs/spirit/workbench/x3/context.cpp b/src/boost/libs/spirit/workbench/x3/context.cpp
new file mode 100644
index 00000000..b7fa5637
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/x3/context.cpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2013 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/spirit/home/x3/support/context.hpp>
+#include <iostream>
+
+using boost::spirit::x3::make_context;
+using boost::spirit::x3::get;
+
+int bb;
+int cc;
+
+struct b_ctx;
+struct c_ctx;
+
+template <typename Context>
+void a(Context const& context)
+{
+ bb = get<b_ctx>(context);
+ cc = get<c_ctx>(context);
+}
+
+template <typename Context>
+void b(Context const& context)
+{
+ int bi = 123;
+ a(make_context<b_ctx>(bi, context));
+}
+
+void c()
+{
+ int ci = 456;
+ b(make_context<c_ctx>(ci));
+}
+
+void test()
+{
+ c();
+
+// MSVC generates this code:
+// mov DWORD PTR ?bb@@3HA, 123
+// mov DWORD PTR ?cc@@3HA, 456
+//
+// GCC generates this code:
+// movl $123, _bb
+// movl $456, _cc
+}
+
diff --git a/src/boost/libs/spirit/workbench/x3/toy/toy.cpp b/src/boost/libs/spirit/workbench/x3/toy/toy.cpp
new file mode 100644
index 00000000..dc0d8801
--- /dev/null
+++ b/src/boost/libs/spirit/workbench/x3/toy/toy.cpp
@@ -0,0 +1,247 @@
+#include <iostream>
+#include <utility>
+#include <cstring>
+#include <boost/mpl/identity.hpp>
+
+namespace boost { namespace spirit { namespace x3
+{
+ template <typename Derived>
+ struct parser
+ {
+ Derived const& derived() const
+ {
+ return *static_cast<Derived const*>(this);
+ }
+ };
+
+ template <typename Char>
+ struct char_parser : parser<char_parser<Char>>
+ {
+ char_parser(Char ch) : ch(ch) {}
+
+ template <typename Iterator, typename Context>
+ bool parse(Iterator& first, Iterator last, Context const& ctx) const
+ {
+ if (first != last && *first == ch)
+ {
+ ++first;
+ return true;
+ }
+ return false;
+ }
+
+ Char ch;
+ };
+
+ template <typename Char>
+ inline char_parser<Char> char_(Char ch)
+ {
+ return char_parser<Char>(ch);
+ };
+
+ template <typename Left, typename Right>
+ struct sequence_parser : parser<sequence_parser<Left, Right>>
+ {
+ sequence_parser(Left left, Right right)
+ : left(left), right(right) {}
+
+ template <typename Iterator, typename Context>
+ bool parse(Iterator& first, Iterator last, Context const& ctx) const
+ {
+ return left.parse(first, last, ctx)
+ && right.parse(first, last, ctx);
+ }
+
+ Left left;
+ Right right;
+ };
+
+ template <typename Left, typename Right>
+ inline sequence_parser<Left, Right> operator>>(
+ parser<Left> const& left, parser<Right> const& right)
+ {
+ return sequence_parser<Left, Right>(
+ left.derived(), right.derived());
+ }
+
+ template <typename Left, typename Right>
+ struct alternative_parser : parser<alternative_parser<Left, Right>>
+ {
+ alternative_parser(Left left, Right right)
+ : left(left), right(right) {}
+
+ template <typename Iterator, typename Context>
+ bool parse(Iterator& first, Iterator last, Context const& ctx) const
+ {
+ if (left.parse(first, last, ctx))
+ return true;
+ return right.parse(first, last, ctx);
+ }
+
+ Left left;
+ Right right;
+ };
+
+ template <typename Left, typename Right>
+ inline alternative_parser<Left, Right> operator|(
+ parser<Left> const& left, parser<Right> const& right)
+ {
+ return alternative_parser<Left, Right>(
+ left.derived(), right.derived());
+ }
+
+ template <typename ID, typename T, typename NextContext>
+ struct context
+ {
+ context(T const& val, NextContext const& next_ctx)
+ : val(val), next_ctx(next_ctx) {}
+
+ T const& get(mpl::identity<ID>) const
+ {
+ return val;
+ }
+
+ template <typename Identity>
+ decltype(std::declval<NextContext>().get(Identity()))
+ get(Identity id) const
+ {
+ return next_ctx.get(id);
+ }
+
+ T const& val;
+ NextContext const& next_ctx;
+ };
+
+ struct empty_context
+ {
+ struct undefined {};
+ template <typename ID>
+ undefined get(ID) const
+ {
+ return undefined();
+ }
+ };
+
+ template <typename ID, typename RHS>
+ struct rule_definition : parser<rule_definition<ID, RHS>>
+ {
+ rule_definition(RHS rhs)
+ : rhs(rhs) {}
+
+ template <typename Iterator, typename Context>
+ bool parse(Iterator& first, Iterator last, Context const& ctx) const
+ {
+ context<ID, RHS, Context> this_ctx(rhs, ctx);
+ return rhs.parse(first, last, this_ctx);
+ }
+
+ RHS rhs;
+ };
+
+ template <typename ID>
+ struct rule : parser<rule<ID>>
+ {
+ template <typename Derived>
+ rule_definition<ID, Derived>
+ operator=(parser<Derived> const& definition) const
+ {
+ return rule_definition<ID, Derived>(definition.derived());
+ }
+
+ template <typename Iterator, typename Context>
+ bool parse(Iterator& first, Iterator last, Context const& ctx) const
+ {
+ return ctx.get(mpl::identity<ID>()).parse(first, last, ctx);
+ }
+ };
+
+ template <typename Iterator, typename Derived>
+ inline bool parse(parser<Derived> const& p, Iterator& first, Iterator last)
+ {
+ empty_context ctx;
+ return p.derived().parse(first, last, ctx);
+ }
+
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// test code
+
+template <typename Parser>
+bool test_parse(Parser const& p, char const* in)
+{
+ return parse(p, in, in + std::strlen(in));
+}
+
+namespace parser
+{
+ using namespace boost::spirit::x3;
+
+ namespace g_definition
+ {
+ auto const x = rule<class x>();
+ auto const ax = char_('a') >> x;
+
+ auto const g =
+ x = char_('x') | ax;
+ }
+ using g_definition::g;
+}
+
+int main()
+{
+
+ { // a non-recursive parser
+ using namespace boost::spirit::x3;
+
+ auto abc = char_('a') >> char_('b') >> char_('c');
+ std::cout << test_parse(abc, "abc") << std::endl;
+ std::cout << test_parse(abc, "abx") << std::endl;
+ std::cout << "==========================================" << std::endl;
+ }
+
+ { // a recursive rule
+ using namespace boost::spirit::x3;
+
+ auto const x = rule<class x>();
+ auto const ax = char_('a') >> x;
+ auto const start = (x = char_('x') | ax);
+
+ std::cout << test_parse(start, "x") << std::endl;
+ std::cout << test_parse(start, "ax") << std::endl;
+ std::cout << test_parse(start, "aaaaax") << std::endl;
+ std::cout << test_parse(start, "aaz") << std::endl;
+ std::cout << "==========================================" << std::endl;
+ }
+
+ { // a grammar ( gcc and clang only: see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html )
+
+ using namespace boost::spirit::x3;
+ auto g = []()
+ {
+ rule<class x> x;
+ auto ax = char_('a') >> x;
+ return x = char_('x') | ax;
+
+ }();
+
+ std::cout << test_parse(g, "x") << std::endl;
+ std::cout << test_parse(g, "ax") << std::endl;
+ std::cout << test_parse(g, "aaaaax") << std::endl;
+ std::cout << test_parse(g, "aaz") << std::endl;
+ std::cout << "==========================================" << std::endl;
+ }
+
+ { // another grammar using namespaces (standard c++, see grammar g definition above in namespace parser.)
+ using parser::g;
+
+ std::cout << test_parse(g, "x") << std::endl;
+ std::cout << test_parse(g, "ax") << std::endl;
+ std::cout << test_parse(g, "aaaaax") << std::endl;
+ std::cout << test_parse(g, "aaz") << std::endl;
+ std::cout << "==========================================" << std::endl;
+ }
+
+ return 0;
+}
+