update boost
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM)
|
||||
#define BOOST_SPIRIT_X3_POSITION_TAGGED_MAY_01_2014_0321PM
|
||||
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
|
||||
|
||||
@@ -18,22 +18,18 @@ namespace boost { namespace spirit { namespace x3
|
||||
template <typename Encoding>
|
||||
struct case_compare
|
||||
{
|
||||
template < template <typename> class basic_charset>
|
||||
typename Encoding::char_type
|
||||
in_set( typename Encoding::char_type const ch
|
||||
, basic_charset<typename Encoding::char_type> const &set)
|
||||
template <typename Char, typename CharSet>
|
||||
bool in_set(Char ch, CharSet const& set)
|
||||
{
|
||||
return set.test(ch);
|
||||
}
|
||||
|
||||
int32_t operator()(
|
||||
typename Encoding::char_type const lc
|
||||
, typename Encoding::char_type const rc) const
|
||||
template <typename Char>
|
||||
int32_t operator()(Char lc, Char rc) const
|
||||
{
|
||||
return lc - rc;
|
||||
}
|
||||
|
||||
|
||||
template <typename CharClassTag>
|
||||
CharClassTag get_char_class_tag(CharClassTag tag) const
|
||||
{
|
||||
@@ -44,20 +40,24 @@ namespace boost { namespace spirit { namespace x3
|
||||
template <typename Encoding>
|
||||
struct no_case_compare
|
||||
{
|
||||
template < template <typename> class basic_charset>
|
||||
typename Encoding::char_type
|
||||
in_set( typename Encoding::char_type const ch
|
||||
, basic_charset<typename Encoding::char_type> const &set)
|
||||
template <typename Char, typename CharSet>
|
||||
bool in_set(Char ch_, CharSet const& set)
|
||||
{
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto ch = char_type(ch_);
|
||||
return set.test(ch)
|
||||
|| set.test(Encoding::islower(ch) ? Encoding::toupper(ch) : Encoding::tolower(ch));
|
||||
|| set.test(Encoding::islower(ch)
|
||||
? Encoding::toupper(ch) : Encoding::tolower(ch));
|
||||
}
|
||||
|
||||
int32_t operator()(
|
||||
typename Encoding::char_type const lc
|
||||
, typename Encoding::char_type const rc) const
|
||||
template <typename Char>
|
||||
int32_t operator()(Char lc_, Char const rc_) const
|
||||
{
|
||||
return Encoding::islower(rc) ? Encoding::tolower(lc) - rc : Encoding::toupper(lc) - rc;
|
||||
using char_type = typename Encoding::classify_type;
|
||||
auto lc = char_type(lc_);
|
||||
auto rc = char_type(rc_);
|
||||
return Encoding::islower(rc)
|
||||
? Encoding::tolower(lc) - rc : Encoding::toupper(lc) - rc;
|
||||
}
|
||||
|
||||
template <typename CharClassTag>
|
||||
@@ -95,6 +95,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
return get_case_compare_impl<Encoding>(x3::get<no_case_tag>(context));
|
||||
}
|
||||
|
||||
auto const no_case_compare_ = no_case_tag{};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -112,19 +112,17 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
template <typename Char>
|
||||
inline static bool is_valid(Char ch)
|
||||
{
|
||||
if (Radix <= 10)
|
||||
return (ch >= '0' && ch <= static_cast<Char>('0' + Radix -1));
|
||||
return (ch >= '0' && ch <= '9')
|
||||
|| (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
|
||||
|| (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
|
||||
return (ch >= '0' && ch <= (Radix > 10 ? '9' : static_cast<Char>('0' + Radix -1)))
|
||||
|| (Radix > 10 && ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
|
||||
|| (Radix > 10 && ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline static unsigned digit(Char ch)
|
||||
{
|
||||
if (Radix <= 10 || (ch >= '0' && ch <= '9'))
|
||||
return ch - '0';
|
||||
return char_encoding::ascii::tolower(ch) - 'a' + 10;
|
||||
return (Radix <= 10 || (ch >= '0' && ch <= '9'))
|
||||
? ch - '0'
|
||||
: char_encoding::ascii::tolower(ch) - 'a' + 10;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -300,6 +298,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4459) // declaration hides global declaration
|
||||
#endif
|
||||
template <typename Iterator, typename Attribute>
|
||||
inline static bool
|
||||
@@ -398,6 +397,7 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4459) // declaration hides global declaration
|
||||
#endif
|
||||
template <typename Iterator, typename Attribute>
|
||||
inline static bool
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/numeric_utils/pow10.hpp>
|
||||
#include <boost/spirit/home/x3/support/numeric_utils/sign.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/move_to.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -29,65 +28,79 @@ namespace boost { namespace spirit { namespace x3 { namespace extension
|
||||
using x3::traits::pow10;
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
inline bool
|
||||
scale(int exp, T& n)
|
||||
{
|
||||
constexpr auto max_exp = std::numeric_limits<T>::max_exponent10;
|
||||
constexpr auto min_exp = std::numeric_limits<T>::min_exponent10;
|
||||
|
||||
if (exp >= 0)
|
||||
{
|
||||
// $$$ Why is this failing for boost.math.concepts ? $$$
|
||||
//~ int nn = std::numeric_limits<T>::max_exponent10;
|
||||
//~ BOOST_ASSERT(exp <= std::numeric_limits<T>::max_exponent10);
|
||||
// return false if exp exceeds the max_exp
|
||||
// do this check only for primitive types!
|
||||
if (is_floating_point<T>() && exp > max_exp)
|
||||
return false;
|
||||
n *= pow10<T>(exp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exp < std::numeric_limits<T>::min_exponent10)
|
||||
if (exp < min_exp)
|
||||
{
|
||||
n /= pow10<T>(-std::numeric_limits<T>::min_exponent10);
|
||||
n /= pow10<T>(-exp + std::numeric_limits<T>::min_exponent10);
|
||||
n /= pow10<T>(-min_exp);
|
||||
|
||||
// return false if exp still exceeds the min_exp
|
||||
// do this check only for primitive types!
|
||||
exp += -min_exp;
|
||||
if (is_floating_point<T>() && exp < min_exp)
|
||||
return false;
|
||||
|
||||
n /= pow10<T>(-exp);
|
||||
}
|
||||
else
|
||||
{
|
||||
n /= pow10<T>(-exp);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
inline bool
|
||||
scale(int /*exp*/, unused_type /*n*/)
|
||||
{
|
||||
// no-op for unused_type
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
inline bool
|
||||
scale(int exp, int frac, T& n)
|
||||
{
|
||||
scale(exp - frac, n);
|
||||
return scale(exp - frac, n);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline bool
|
||||
scale(int /*exp*/, int /*frac*/, unused_type /*n*/)
|
||||
{
|
||||
// no-op for unused_type
|
||||
return true;
|
||||
}
|
||||
|
||||
inline float
|
||||
negate(bool neg, float n)
|
||||
{
|
||||
return neg ? x3::changesign(n) : n;
|
||||
return neg ? (std::copysignf)(n, -1.f) : n;
|
||||
}
|
||||
|
||||
inline double
|
||||
negate(bool neg, double n)
|
||||
{
|
||||
return neg ? x3::changesign(n) : n;
|
||||
return neg ? (std::copysign)(n, -1.) : n;
|
||||
}
|
||||
|
||||
inline long double
|
||||
negate(bool neg, long double n)
|
||||
{
|
||||
return neg ? x3::changesign(n) : n;
|
||||
return neg ? (std::copysignl)(n, -1.) : n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -150,6 +163,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
|
||||
bool e_hit = false;
|
||||
Iterator e_pos;
|
||||
int frac_digits = 0;
|
||||
|
||||
// Try to parse the dot ('.' decimal point)
|
||||
@@ -178,6 +192,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
|
||||
// Now, let's see if we can parse the exponent prefix
|
||||
e_pos = first;
|
||||
e_hit = p.parse_exp(first, last);
|
||||
}
|
||||
else
|
||||
@@ -191,6 +206,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
|
||||
// If we must expect a dot and we didn't see an exponent
|
||||
// prefix, return no-match.
|
||||
e_pos = first;
|
||||
e_hit = p.parse_exp(first, last);
|
||||
if (p.expect_dot && !e_hit)
|
||||
{
|
||||
@@ -208,19 +224,25 @@ namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
// Got the exponent value. Scale the number by
|
||||
// exp-frac_digits.
|
||||
extension::scale(exp, frac_digits, n);
|
||||
if (!extension::scale(exp, frac_digits, n))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oops, no exponent, return no-match.
|
||||
first = save;
|
||||
return false;
|
||||
// If there is no number, disregard the exponent altogether.
|
||||
// by resetting 'first' prior to the exponent prefix (e|E)
|
||||
first = e_pos;
|
||||
|
||||
// Scale the number by -frac_digits.
|
||||
if (!extension::scale(-frac_digits, n))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (frac_digits)
|
||||
{
|
||||
// No exponent found. Scale the number by -frac_digits.
|
||||
extension::scale(-frac_digits, n);
|
||||
if (!extension::scale(-frac_digits, n))
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we got a negative sign, negate the number
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/numeric_traits.hpp>
|
||||
#include <cfloat>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# pragma warning(push)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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_X3_SIGN_MAR_11_2009_0734PM)
|
||||
#define BOOST_SPIRIT_X3_SIGN_MAR_11_2009_0734PM
|
||||
|
||||
#include <boost/math/special_functions/sign.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template<typename T>
|
||||
inline bool (signbit)(T x)
|
||||
{
|
||||
return (boost::math::signbit)(x) ? true : false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T (changesign)(T x)
|
||||
{
|
||||
return (boost::math::changesign)(x);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2013 Agustín Bergé
|
||||
Copyright (c) 2013 Agustin Berge
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the attribute type of a component. By default, this gets the
|
||||
// Component's attribute_type typedef or instantiates a nested attribute
|
||||
// Get the attribute type of a component. By default, this gets the
|
||||
// Component's attribute_type typedef or instantiates a nested attribute
|
||||
// metafunction. Components may specialize this if such an attribute_type
|
||||
// is not readily available (e.g. expensive to compute at compile time).
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -28,28 +28,27 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Component, typename Context, typename Enable = void>
|
||||
struct default_attribute_of;
|
||||
|
||||
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::attribute_type>::type>
|
||||
: mpl::identity<typename Component::attribute_type> {};
|
||||
|
||||
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename disable_if_substitution_failure<
|
||||
typename Component::template attribute<Context>::type>::type>
|
||||
: Component::template attribute<Context> {};
|
||||
|
||||
|
||||
template <typename Component, typename Context>
|
||||
struct default_attribute_of<Component, Context,
|
||||
typename enable_if_c<Component::is_pass_through_unary>::type>
|
||||
: attribute_of<typename Component::subject_type, Context>{};
|
||||
}
|
||||
|
||||
|
||||
template <typename Component, typename Context, typename Enable>
|
||||
struct attribute_of : detail::default_attribute_of<Component, Context> {};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2020 Nikita Kniazev
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
#ifndef BOOST_SPIRIT_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY
|
||||
#define BOOST_SPIRIT_X3_SUPPORT_TRAITS_ATTRIBUTE_OF_BINARY
|
||||
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/type_traits/type_identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
template <typename... T>
|
||||
struct type_sequence
|
||||
{
|
||||
using type = type_sequence;
|
||||
|
||||
static const int size = sizeof...(T);
|
||||
|
||||
template <typename... U>
|
||||
using append = type_sequence<T..., U...>;
|
||||
|
||||
template <typename... U>
|
||||
using prepend = type_sequence<U..., T...>;
|
||||
|
||||
template <typename U>
|
||||
using extend = typename U::template prepend<T...>;
|
||||
|
||||
template <template <typename...> class U>
|
||||
using transfer_to = U<T...>;
|
||||
};
|
||||
|
||||
template <typename Attribute>
|
||||
struct types_of_binary_init : type_sequence<Attribute> {};
|
||||
template <>
|
||||
struct types_of_binary_init<unused_type> : type_sequence<> {};
|
||||
template <>
|
||||
struct types_of_binary_init<unused_type const> : type_sequence<> {};
|
||||
|
||||
template <template <typename, typename> class B, typename P, typename C>
|
||||
struct get_types_of_binary
|
||||
: types_of_binary_init<typename traits::attribute_of<P, C>::type> {};
|
||||
template <template <typename, typename> class B, typename L, typename R, typename C>
|
||||
struct get_types_of_binary<B, B<L, R>, C>
|
||||
: get_types_of_binary<B, L, C>::template extend<get_types_of_binary<B, R, C>> {};
|
||||
|
||||
template <template <typename...> class A, typename T, int = T::size>
|
||||
struct type_sequence_to_attribute { using type = typename T::template transfer_to<A>; };
|
||||
template <template <typename...> class A, typename T>
|
||||
struct type_sequence_to_attribute<A, T, 1> : T::template transfer_to<type_identity> {};
|
||||
template <template <typename...> class A, typename T>
|
||||
struct type_sequence_to_attribute<A, T, 0> { using type = unused_type; };
|
||||
|
||||
template <template <typename...> class A, template <typename, typename> class B,
|
||||
typename L, typename R, typename C>
|
||||
using attribute_of_binary = type_sequence_to_attribute<A,
|
||||
typename get_types_of_binary<B, B<L, R>, C>::type>;
|
||||
}}}}
|
||||
#endif
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <boost/fusion/support/category_of.hpp>
|
||||
#include <boost/spirit/home/x3/support/unused.hpp>
|
||||
#include <boost/fusion/include/deque.hpp>
|
||||
#include <boost/tti/has_type.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -28,30 +28,27 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
|
||||
namespace detail
|
||||
{
|
||||
BOOST_TTI_HAS_TYPE(value_type)
|
||||
BOOST_TTI_HAS_TYPE(iterator)
|
||||
BOOST_TTI_HAS_TYPE(size_type)
|
||||
BOOST_TTI_HAS_TYPE(reference)
|
||||
BOOST_TTI_HAS_TYPE(key_type)
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_container_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_container_impl<T, void_t<
|
||||
typename T::value_type, typename T::iterator,
|
||||
typename T::size_type, typename T::reference> > : mpl::true_ {};
|
||||
|
||||
template <typename T, typename Enabler = void>
|
||||
struct is_associative_impl : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_associative_impl<T, void_t<typename T::key_type>>
|
||||
: mpl::true_ {};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using is_container = mpl::bool_<
|
||||
detail::has_type_value_type<T>::value &&
|
||||
detail::has_type_iterator<T>::value &&
|
||||
detail::has_type_size_type<T>::value &&
|
||||
detail::has_type_reference<T>::value>;
|
||||
using is_container = typename detail::is_container_impl<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_associative = mpl::bool_<
|
||||
detail::has_type_key_type<T>::value>;
|
||||
|
||||
template<typename T, typename Enable = void>
|
||||
struct is_reservable : mpl::false_ {};
|
||||
|
||||
template<typename T>
|
||||
struct is_reservable<T, decltype(std::declval<T&>().reserve(0))>
|
||||
: mpl::true_ {};
|
||||
using is_associative = typename detail::is_associative_impl<T>::type;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
@@ -158,18 +155,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
struct append_container
|
||||
{
|
||||
private:
|
||||
template <typename Iterator>
|
||||
static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_)
|
||||
{
|
||||
// Not all containers have "reserve"
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void reserve(Container& c, Iterator first, Iterator last, mpl::true_)
|
||||
{
|
||||
c.reserve(c.size() + std::distance(first, last));
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
|
||||
{
|
||||
@@ -186,7 +171,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename Iterator>
|
||||
static bool call(Container& c, Iterator first, Iterator last)
|
||||
{
|
||||
reserve(c, first, last, is_reservable<Container>{});
|
||||
insert(c, first, last, is_associative<Container>{});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_IS_RANGE_DEC_06_2017_1900PM)
|
||||
#define BOOST_SPIRIT_X3_IS_RANGE_DEC_06_2017_1900PM
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/range_fwd.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{};
|
||||
|
||||
template <typename T, typename Attribute, typename Enable = void>
|
||||
struct is_substitute_impl : is_same<T, Attribute> {};
|
||||
struct is_substitute_impl : mpl::false_ {};
|
||||
|
||||
template <typename T, typename Attribute>
|
||||
struct is_substitute_impl<T, Attribute,
|
||||
@@ -75,16 +75,15 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
typename enable_if<
|
||||
is_variant<Attribute>
|
||||
>::type>
|
||||
: mpl::or_<
|
||||
is_same<T, Attribute>
|
||||
, variant_has_substitute<Attribute, T>
|
||||
>
|
||||
: variant_has_substitute<Attribute, T>
|
||||
{};
|
||||
}
|
||||
|
||||
template <typename T, typename Attribute, typename Enable /*= void*/>
|
||||
struct is_substitute
|
||||
: detail::is_substitute_impl<T, Attribute> {};
|
||||
: mpl::or_<
|
||||
is_same<T, Attribute>,
|
||||
detail::is_substitute_impl<T, Attribute>> {};
|
||||
|
||||
// for reference T
|
||||
template <typename T, typename Attribute, typename Enable>
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/tuple_traits.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/variant_has_substitute.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/fusion/include/is_sequence.hpp>
|
||||
#include <boost/fusion/include/front.hpp>
|
||||
#include <boost/fusion/include/move.hpp>
|
||||
@@ -51,37 +53,37 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&&, Dest&, unused_attribute) {}
|
||||
move_to(Source&, Dest&, unused_attribute) {}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source&& src, Dest& dest, mpl::false_) // src is not a single-element tuple
|
||||
move_to_plain(Source& src, Dest& dest, mpl::false_) // src is not a single-element tuple
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_plain(Source&& src, Dest& dest, mpl::true_) // src is a single-element tuple
|
||||
move_to_plain(Source& src, Dest& dest, mpl::true_) // src is a single-element tuple
|
||||
{
|
||||
dest = std::move(fusion::front(src));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&& src, Dest& dest, plain_attribute)
|
||||
move_to(Source& src, Dest& dest, plain_attribute)
|
||||
{
|
||||
typename mpl::and_<
|
||||
fusion::traits::is_sequence<Source>,
|
||||
is_size_one_sequence<Source> >
|
||||
is_single_element_sequence;
|
||||
|
||||
move_to_plain(std::forward<Source>(src), dest, is_single_element_sequence);
|
||||
move_to_plain(src, dest, is_single_element_sequence);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<is_container<Source>>::type
|
||||
move_to(Source&& src, Dest& dest, container_attribute)
|
||||
move_to(Source& src, Dest& dest, container_attribute)
|
||||
{
|
||||
traits::move_to(src.begin(), src.end(), dest);
|
||||
}
|
||||
@@ -92,30 +94,30 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
is_same_size_sequence<Dest, Source>,
|
||||
mpl::not_<is_size_one_sequence<Dest> > >
|
||||
>::type
|
||||
move_to(Source&& src, Dest& dest, tuple_attribute)
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
fusion::move(std::forward<Source>(src), dest);
|
||||
fusion::move(std::move(src), dest);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline typename enable_if<
|
||||
is_size_one_sequence<Dest>
|
||||
>::type
|
||||
move_to(Source&& src, Dest& dest, tuple_attribute)
|
||||
move_to(Source& src, Dest& dest, tuple_attribute)
|
||||
{
|
||||
traits::move_to(std::forward<Source>(src), fusion::front(dest));
|
||||
traits::move_to(src, fusion::front(dest));
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&& src, Dest& dest, variant_attribute, mpl::false_)
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::false_)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::false_)
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::false_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// cannot directly hold. We'll try to unwrap the single element fusion sequence.
|
||||
@@ -129,7 +131,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to_variant_from_single_element_sequence(Source&& src, Dest& dest, mpl::true_)
|
||||
move_to_variant_from_single_element_sequence(Source& src, Dest& dest, mpl::true_)
|
||||
{
|
||||
// dest is a variant, src is a single element fusion sequence that the variant
|
||||
// *can* directly hold.
|
||||
@@ -138,21 +140,21 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&& src, Dest& dest, variant_attribute, mpl::true_)
|
||||
move_to(Source& src, Dest& dest, variant_attribute, mpl::true_)
|
||||
{
|
||||
move_to_variant_from_single_element_sequence(src, dest, variant_has_substitute<Dest, Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&& src, Dest& dest, variant_attribute tag)
|
||||
move_to(Source& src, Dest& dest, variant_attribute tag)
|
||||
{
|
||||
move_to(src, dest, tag, is_size_one_sequence<Source>());
|
||||
}
|
||||
|
||||
template <typename Source, typename Dest>
|
||||
inline void
|
||||
move_to(Source&& src, Dest& dest, optional_attribute)
|
||||
move_to(Source& src, Dest& dest, optional_attribute)
|
||||
{
|
||||
dest = std::move(src);
|
||||
}
|
||||
@@ -191,29 +193,28 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename Source, typename Dest>
|
||||
inline void move_to(Source&& src, Dest& dest)
|
||||
{
|
||||
detail::move_to(std::move(src), dest
|
||||
, typename attribute_category<Dest>::type());
|
||||
detail::move_to(src, dest, typename attribute_category<Dest>::type());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T& src, T& dest)
|
||||
{
|
||||
if (boost::addressof(src) != boost::addressof(dest))
|
||||
dest = std::move(src);
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T const& src, T& dest)
|
||||
{
|
||||
if (boost::addressof(src) != boost::addressof(dest))
|
||||
dest = std::move(src);
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = src;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void move_to(T&& src, T& dest)
|
||||
{
|
||||
if (boost::addressof(src) != boost::addressof(dest))
|
||||
dest = std::move(src);
|
||||
BOOST_ASSERT(boost::addressof(src) != boost::addressof(dest));
|
||||
dest = std::move(src);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Dest>
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
# include <boost/spirit/home/support/char_encoding/unicode.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
@@ -67,9 +70,8 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename Out, typename T, typename Enable = void>
|
||||
struct print_attribute_debug
|
||||
{
|
||||
// for plain data types
|
||||
template <typename T_>
|
||||
static void call(Out& out, T_ const& val, unused_attribute)
|
||||
// for unused_type
|
||||
static void call(Out& out, unused_type, unused_attribute)
|
||||
{
|
||||
out << "unused";
|
||||
}
|
||||
@@ -81,6 +83,28 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
out << val;
|
||||
}
|
||||
|
||||
#ifdef BOOST_SPIRIT_X3_UNICODE
|
||||
static void call(Out& out, char_encoding::unicode::char_type val, plain_attribute)
|
||||
{
|
||||
if (val >= 0 && val < 127)
|
||||
{
|
||||
if (iscntrl(val))
|
||||
out << "\\" << std::oct << int(val) << std::dec;
|
||||
else if (isprint(val))
|
||||
out << char(val);
|
||||
else
|
||||
out << "\\x" << std::hex << int(val) << std::dec;
|
||||
}
|
||||
else
|
||||
out << "\\x" << std::hex << int(val) << std::dec;
|
||||
}
|
||||
|
||||
static void call(Out& out, char val, plain_attribute tag)
|
||||
{
|
||||
call(out, static_cast<char_encoding::unicode::char_type>(val), tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// for fusion data types
|
||||
template <typename T_>
|
||||
static void call(Out& out, T_ const& val, tuple_attribute)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <cctype>
|
||||
#include <ios>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
@@ -36,10 +37,17 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
case '\t': o << "\\t"; break;
|
||||
case '\v': o << "\\v"; break;
|
||||
default:
|
||||
if (c >= 0 && c < 127 && iscntrl(c))
|
||||
if (c >= 0 && c < 127)
|
||||
{
|
||||
if (iscntrl(c))
|
||||
o << "\\" << std::oct << int(c);
|
||||
else if (isprint(c))
|
||||
o << char(c);
|
||||
else
|
||||
o << "\\x" << std::hex << int(c);
|
||||
}
|
||||
else
|
||||
o << Char(c);
|
||||
o << "\\x" << std::hex << int(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2019 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)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM)
|
||||
#define BOOST_SPIRIT_X3_PSEUDO_ATTRIBUTE_OF_MAY_15_2019_1012PM
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Pseudo attributes are placeholders for parsers that can only know
|
||||
// its actual attribute at parse time. This trait customization point
|
||||
// provides a mechanism to convert the trait to the actual trait at
|
||||
// parse time.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename Context, typename Attribute, typename Iterator
|
||||
, typename Enable = void>
|
||||
struct pseudo_attribute
|
||||
{
|
||||
using attribute_type = Attribute;
|
||||
using type = Attribute;
|
||||
|
||||
static type&& call(Iterator&, Iterator const&, attribute_type&& attribute)
|
||||
{
|
||||
return std::forward<type>(attribute);
|
||||
}
|
||||
};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -11,128 +11,9 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Determine if T is a character type
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_char : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_char<T const> : is_char<T> {};
|
||||
|
||||
template <>
|
||||
struct is_char<char> : mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct is_char<wchar_t> : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Determine if T is a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct is_string : mpl::false_ {};
|
||||
|
||||
template <typename T>
|
||||
struct is_string<T const> : is_string<T> {};
|
||||
|
||||
template <>
|
||||
struct is_string<char const*> : mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct is_string<wchar_t const*> : mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct is_string<char*> : mpl::true_ {};
|
||||
|
||||
template <>
|
||||
struct is_string<wchar_t*> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<char[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<wchar_t[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<char const[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<wchar_t const[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<char(&)[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<wchar_t(&)[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<char const(&)[N]> : mpl::true_ {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct is_string<wchar_t const(&)[N]> : mpl::true_ {};
|
||||
|
||||
template <typename T, typename Traits, typename Allocator>
|
||||
struct is_string<std::basic_string<T, Traits, Allocator> > : mpl::true_ {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the underlying char type of a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct char_type_of;
|
||||
|
||||
template <typename T>
|
||||
struct char_type_of<T const> : char_type_of<T> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<char> : mpl::identity<char> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<wchar_t> : mpl::identity<wchar_t> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<char const*> : mpl::identity<char const> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<wchar_t const*> : mpl::identity<wchar_t const> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<char*> : mpl::identity<char> {};
|
||||
|
||||
template <>
|
||||
struct char_type_of<wchar_t*> : mpl::identity<wchar_t> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<char[N]> : mpl::identity<char> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<wchar_t[N]> : mpl::identity<wchar_t> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<char const[N]> : mpl::identity<char const> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<wchar_t const[N]> : mpl::identity<wchar_t const> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<char(&)[N]> : mpl::identity<char> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<wchar_t(&)[N]> : mpl::identity<wchar_t> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<char const(&)[N]> : mpl::identity<char const> {};
|
||||
|
||||
template <std::size_t N>
|
||||
struct char_type_of<wchar_t const(&)[N]> : mpl::identity<wchar_t const> {};
|
||||
|
||||
template <typename T, typename Traits, typename Allocator>
|
||||
struct char_type_of<std::basic_string<T, Traits, Allocator> >
|
||||
: mpl::identity<T> {};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Get the C string from a string
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -142,8 +23,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename String>
|
||||
struct extract_c_string
|
||||
{
|
||||
typedef typename char_type_of<String>::type char_type;
|
||||
|
||||
template <typename T>
|
||||
static T const* call (T* str)
|
||||
{
|
||||
@@ -161,9 +40,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename T>
|
||||
struct extract_c_string<T const>
|
||||
{
|
||||
typedef typename extract_c_string<T>::char_type char_type;
|
||||
|
||||
static typename extract_c_string<T>::char_type const* call (T const str)
|
||||
static decltype(auto) call(T const str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
@@ -173,9 +50,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename T>
|
||||
struct extract_c_string<T&>
|
||||
{
|
||||
typedef typename extract_c_string<T>::char_type char_type;
|
||||
|
||||
static typename extract_c_string<T>::char_type const* call (T& str)
|
||||
static decltype(auto) call(T& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
@@ -185,9 +60,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename T>
|
||||
struct extract_c_string<T const&>
|
||||
{
|
||||
typedef typename extract_c_string<T>::char_type char_type;
|
||||
|
||||
static typename extract_c_string<T>::char_type const* call (T const& str)
|
||||
static decltype(auto) call(T const& str)
|
||||
{
|
||||
return extract_c_string<T>::call(str);
|
||||
}
|
||||
@@ -196,8 +69,6 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
template <typename T, typename Traits, typename Allocator>
|
||||
struct extract_c_string<std::basic_string<T, Traits, Allocator> >
|
||||
{
|
||||
typedef T char_type;
|
||||
|
||||
typedef std::basic_string<T, Traits, Allocator> string;
|
||||
|
||||
static T const* call (string const& str)
|
||||
@@ -207,29 +78,25 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
typename extract_c_string<T*>::char_type const*
|
||||
get_c_string(T* str)
|
||||
decltype(auto) get_c_string(T* str)
|
||||
{
|
||||
return extract_c_string<T*>::call(str);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename extract_c_string<T const*>::char_type const*
|
||||
get_c_string(T const* str)
|
||||
decltype(auto) get_c_string(T const* str)
|
||||
{
|
||||
return extract_c_string<T const*>::call(str);
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
typename extract_c_string<String>::char_type const*
|
||||
get_c_string(String& str)
|
||||
decltype(auto) get_c_string(String& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
|
||||
template <typename String>
|
||||
typename extract_c_string<String>::char_type const*
|
||||
get_c_string(String const& str)
|
||||
decltype(auto) get_c_string(String const& str)
|
||||
{
|
||||
return extract_c_string<String>::call(str);
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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_X3_VALUE_TRAITS_MAY_07_2013_0203PM)
|
||||
#define BOOST_SPIRIT_X3_VALUE_TRAITS_MAY_07_2013_0203PM
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename T, typename Enable = void>
|
||||
struct value_initialize
|
||||
{
|
||||
static T call()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -13,22 +13,22 @@
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Variant, typename Attribute>
|
||||
template <typename Variant, typename T>
|
||||
struct variant_find_substitute
|
||||
{
|
||||
// Get the type from the variant that can be a substitute for Attribute.
|
||||
// If none is found, just return Attribute
|
||||
// Get the type from the Variant that can be a substitute for T.
|
||||
// If none is found, just return T
|
||||
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
typedef typename mpl::find<types, Attribute>::type iter_1;
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute> >,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1> >,
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
@@ -36,7 +36,7 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter, end>,
|
||||
mpl::identity<Attribute>,
|
||||
mpl::identity<T>,
|
||||
mpl::deref<iter>
|
||||
>::type
|
||||
type;
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
{
|
||||
template <typename Variant, typename Attribute>
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute_impl
|
||||
{
|
||||
// Find a type from the variant that can be a substitute for Attribute.
|
||||
// Find a type from the Variant that can be a substitute for T.
|
||||
// return true_ if one is found, else false_
|
||||
|
||||
typedef Variant variant_type;
|
||||
typedef typename variant_type::types types;
|
||||
typedef typename mpl::end<types>::type end;
|
||||
|
||||
typedef typename mpl::find<types, Attribute>::type iter_1;
|
||||
typedef typename mpl::find<types, T>::type iter_1;
|
||||
|
||||
typedef typename
|
||||
mpl::eval_if<
|
||||
is_same<iter_1, end>,
|
||||
mpl::find_if<types, traits::is_substitute<mpl::_1, Attribute>>,
|
||||
mpl::find_if<types, traits::is_substitute<T, mpl::_1>>,
|
||||
mpl::identity<iter_1>
|
||||
>::type
|
||||
iter;
|
||||
@@ -36,15 +36,15 @@ namespace boost { namespace spirit { namespace x3 { namespace traits
|
||||
typedef mpl::not_<is_same<iter, end>> type;
|
||||
};
|
||||
|
||||
template <typename Variant, typename Attribute>
|
||||
template <typename Variant, typename T>
|
||||
struct variant_has_substitute
|
||||
: variant_has_substitute_impl<Variant, Attribute>::type {};
|
||||
: variant_has_substitute_impl<Variant, T>::type {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct variant_has_substitute<unused_type, Attribute> : mpl::true_ {};
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type, T> : mpl::true_ {};
|
||||
|
||||
template <typename Attribute>
|
||||
struct variant_has_substitute<unused_type const, Attribute> : mpl::true_ {};
|
||||
template <typename T>
|
||||
struct variant_has_substitute<unused_type const, T> : mpl::true_ {};
|
||||
|
||||
}}}}
|
||||
|
||||
|
||||
@@ -10,19 +10,12 @@
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4522) // multiple assignment operators specified warning
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
struct unused_type
|
||||
{
|
||||
unused_type()
|
||||
{
|
||||
}
|
||||
unused_type() = default;
|
||||
|
||||
template <typename T>
|
||||
unused_type(T const&)
|
||||
@@ -43,18 +36,6 @@ namespace boost { namespace spirit { namespace x3
|
||||
return *this;
|
||||
}
|
||||
|
||||
unused_type const&
|
||||
operator=(unused_type const&) const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
unused_type&
|
||||
operator=(unused_type const&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// unused_type can also masquerade as an empty context (see context.hpp)
|
||||
|
||||
template <typename ID>
|
||||
@@ -62,23 +43,19 @@ namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, unused_type const&)
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
friend std::istream& operator>>(std::istream& in, unused_type&)
|
||||
{
|
||||
return in;
|
||||
}
|
||||
};
|
||||
|
||||
auto const unused = unused_type{};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, unused_type const&)
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, unused_type&)
|
||||
{
|
||||
return in;
|
||||
}
|
||||
constexpr auto unused = unused_type{};
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <boost/spirit/home/x3/support/context.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/lambda_visitor.hpp>
|
||||
#include <boost/spirit/home/x3/support/traits/is_variant.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
@@ -40,9 +41,16 @@ namespace boost { namespace spirit { namespace x3
|
||||
|
||||
template <typename T, typename Iterator, typename Context>
|
||||
inline void on_success(Iterator const& first, Iterator const& last
|
||||
, forward_ast<T>& ast, Context const& context)
|
||||
{
|
||||
this->on_success(first, last, ast.get(), context);
|
||||
}
|
||||
|
||||
template <typename T, typename Iterator, typename Context>
|
||||
inline typename disable_if<traits::is_variant<T>>::type on_success(Iterator const& first, Iterator const& last
|
||||
, T& ast, Context const& context)
|
||||
{
|
||||
auto& error_handler = get<error_handler_tag>(context).get();
|
||||
auto& error_handler = x3::get<error_handler_tag>(context).get();
|
||||
error_handler.tag(ast, first, last);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7,12 +7,8 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM)
|
||||
#define BOOST_SPIRIT_X3_ERROR_REPORTING_MAY_19_2014_00405PM
|
||||
|
||||
#ifndef BOOST_SPIRIT_X3_NO_FILESYSTEM
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/utf8.hpp>
|
||||
#include <ostream>
|
||||
|
||||
// Clang-style error handling utilities
|
||||
@@ -68,8 +64,6 @@ namespace boost { namespace spirit { namespace x3
|
||||
void print_file_line(std::size_t line) const;
|
||||
void print_line(Iterator line_start, Iterator last) const;
|
||||
void print_indicator(Iterator& line_start, Iterator last, char ind) const;
|
||||
void skip_whitespace(Iterator& err_pos, Iterator last) const;
|
||||
void skip_non_whitespace(Iterator& err_pos, Iterator last) const;
|
||||
Iterator get_line_start(Iterator first, Iterator pos) const;
|
||||
std::size_t position(Iterator i) const;
|
||||
|
||||
@@ -84,12 +78,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
if (file != "")
|
||||
{
|
||||
#ifdef BOOST_SPIRIT_X3_NO_FILESYSTEM
|
||||
err_out << "In file " << file << ", ";
|
||||
#else
|
||||
namespace fs = boost::filesystem;
|
||||
err_out << "In file " << fs::path(file).generic_string() << ", ";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,7 +102,7 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
typedef typename std::iterator_traits<Iterator>::value_type char_type;
|
||||
std::basic_string<char_type> line{start, end};
|
||||
err_out << locale::conv::utf_to_utf<char>(line) << std::endl;
|
||||
err_out << x3::to_utf8(line) << std::endl;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
@@ -132,41 +121,15 @@ namespace boost { namespace spirit { namespace x3
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void error_handler<Iterator>::skip_whitespace(Iterator& err_pos, Iterator last) const
|
||||
{
|
||||
// make sure err_pos does not point to white space
|
||||
while (err_pos != last)
|
||||
{
|
||||
char c = *err_pos;
|
||||
if (std::isspace(c))
|
||||
++err_pos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void error_handler<Iterator>::skip_non_whitespace(Iterator& err_pos, Iterator last) const
|
||||
{
|
||||
// make sure err_pos does not point to white space
|
||||
while (err_pos != last)
|
||||
{
|
||||
char c = *err_pos;
|
||||
if (std::isspace(c))
|
||||
break;
|
||||
else
|
||||
++err_pos;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
inline Iterator error_handler<Iterator>::get_line_start(Iterator first, Iterator pos) const
|
||||
{
|
||||
Iterator latest = first;
|
||||
for (Iterator i = first; i != pos; ++i)
|
||||
for (Iterator i = first; i != pos;)
|
||||
if (*i == '\r' || *i == '\n')
|
||||
latest = i;
|
||||
latest = ++i;
|
||||
else
|
||||
++i;
|
||||
return latest;
|
||||
}
|
||||
|
||||
@@ -201,15 +164,10 @@ namespace boost { namespace spirit { namespace x3
|
||||
Iterator first = pos_cache.first();
|
||||
Iterator last = pos_cache.last();
|
||||
|
||||
// make sure err_pos does not point to white space
|
||||
skip_whitespace(err_pos, last);
|
||||
|
||||
print_file_line(position(err_pos));
|
||||
err_out << error_message << std::endl;
|
||||
|
||||
Iterator start = get_line_start(first, err_pos);
|
||||
if (start != first)
|
||||
++start;
|
||||
print_line(start, last);
|
||||
print_indicator(start, err_pos, '_');
|
||||
err_out << "^_" << std::endl;
|
||||
@@ -222,15 +180,10 @@ namespace boost { namespace spirit { namespace x3
|
||||
Iterator first = pos_cache.first();
|
||||
Iterator last = pos_cache.last();
|
||||
|
||||
// make sure err_pos does not point to white space
|
||||
skip_whitespace(err_first, last);
|
||||
|
||||
print_file_line(position(err_first));
|
||||
err_out << error_message << std::endl;
|
||||
|
||||
Iterator start = get_line_start(first, err_first);
|
||||
if (start != first)
|
||||
++start;
|
||||
print_line(start, last);
|
||||
print_indicator(start, err_first, ' ');
|
||||
print_indicator(start, err_last, '~');
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define BOOST_SPIRIT_X3_IS_CALLABLE_HPP_INCLUDED
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
{
|
||||
@@ -16,8 +15,8 @@ namespace boost { namespace spirit { namespace x3 { namespace detail
|
||||
struct is_callable_impl : mpl::false_ {};
|
||||
|
||||
template <typename F, typename... A>
|
||||
struct is_callable_impl<F(A...), typename disable_if_substitution_failure<
|
||||
decltype(std::declval<F>()(std::declval<A>()...))>::type>
|
||||
struct is_callable_impl<F(A...),
|
||||
decltype(void(std::declval<F>()(std::declval<A>()...)))>
|
||||
: mpl::true_
|
||||
{};
|
||||
}}}}
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2015 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)
|
||||
=============================================================================*/
|
||||
#if !defined(BOOST_SPIRIT_X3_TEST_UTILITIES)
|
||||
#define BOOST_SPIRIT_X3_TEST_UTILITIES
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3 { namespace testing
|
||||
{
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// compare
|
||||
//
|
||||
// Compares the contents of in with the template tem. The template
|
||||
// may include embedded regular expressions marked up within re_prefix
|
||||
// and re_suffix tags. For example, given the default RE markup, this
|
||||
// template <%[0-9]+%> will match any integer in in. The function
|
||||
// will return the first non-matching position. The flag full_match
|
||||
// indicates a full match. It is possible for returned pos to be
|
||||
// at the end of in (in.end()) while still returning full_match ==
|
||||
// false. In that case, we have a partial match.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Iterator>
|
||||
struct compare_result
|
||||
{
|
||||
compare_result(
|
||||
Iterator pos
|
||||
, bool full_match
|
||||
) : pos(pos), full_match(full_match) {}
|
||||
|
||||
Iterator pos;
|
||||
bool full_match;
|
||||
};
|
||||
|
||||
template <typename Range>
|
||||
compare_result<typename Range::const_iterator>
|
||||
compare(
|
||||
Range const& in
|
||||
, Range const& tem
|
||||
, char const* re_prefix = "<%"
|
||||
, char const* re_suffix = "%>"
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// compare
|
||||
//
|
||||
// 1) Call f, given the contents of input_path loaded in a string.
|
||||
// The result of calling f is the output string.
|
||||
// 2) Compare the result of calling f with expected template
|
||||
// file (expect_path) using the low-level compare utility
|
||||
// abive
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
template <typename F>
|
||||
bool compare(
|
||||
fs::path input_path, fs::path expect_path
|
||||
, F f
|
||||
, char const* re_prefix = "<%"
|
||||
, char const* re_suffix = "%>"
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// for_each_file
|
||||
//
|
||||
// For each *.input and *.expect file in a given directory,
|
||||
// call the function f, passing in the *.input and *.expect paths.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
template <typename F>
|
||||
int for_each_file(fs::path p, F f);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// load_file
|
||||
//
|
||||
// Load file into a string.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
std::string load(fs::path p);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Implementation
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Iterator>
|
||||
inline bool is_regex(
|
||||
Iterator& first
|
||||
, Iterator last
|
||||
, std::string& re
|
||||
, char const* re_prefix
|
||||
, char const* re_suffix
|
||||
)
|
||||
{
|
||||
boost::regex e(re_prefix + std::string("(.*?)") + re_suffix);
|
||||
boost::match_results<Iterator> what;
|
||||
if (boost::regex_search(
|
||||
first, last, what, e
|
||||
, boost::match_default | boost::match_continuous))
|
||||
{
|
||||
re = what[1].str();
|
||||
first = what[0].second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
inline compare_result<typename Range::const_iterator>
|
||||
compare(
|
||||
Range const& in
|
||||
, Range const& tem
|
||||
, char const* re_prefix
|
||||
, char const* re_suffix
|
||||
)
|
||||
{
|
||||
typedef typename Range::const_iterator iter_t;
|
||||
typedef compare_result<iter_t> compare_result_t;
|
||||
|
||||
iter_t in_first = in.begin();
|
||||
iter_t in_last = in.end();
|
||||
iter_t tem_first = tem.begin();
|
||||
iter_t tem_last = tem.end();
|
||||
std::string re;
|
||||
|
||||
while (in_first != in_last && tem_first != tem_last)
|
||||
{
|
||||
if (is_regex(tem_first, tem_last, re, re_prefix, re_suffix))
|
||||
{
|
||||
boost::match_results<iter_t> what;
|
||||
boost::regex e(re);
|
||||
if (!boost::regex_search(
|
||||
in_first, in_last, what, e
|
||||
, boost::match_default | boost::match_continuous))
|
||||
{
|
||||
// RE mismatch: exit now.
|
||||
return compare_result_t(in_first, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// RE match: gobble the matching string.
|
||||
in_first = what[0].second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Char by char comparison. Exit if we have a mismatch.
|
||||
if (*in_first++ != *tem_first++)
|
||||
return compare_result_t(in_first, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore trailing spaces in template
|
||||
bool has_trailing_nonspaces = false;
|
||||
while (tem_first != tem_last)
|
||||
{
|
||||
if (!std::isspace(*tem_first++))
|
||||
{
|
||||
has_trailing_nonspaces = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (in_first != in_last)
|
||||
{
|
||||
if (!std::isspace(*in_first++))
|
||||
{
|
||||
has_trailing_nonspaces = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// return a full match only if the template is fully matched and if there
|
||||
// are no more characters to match in the source
|
||||
return compare_result_t(in_first, !has_trailing_nonspaces);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline int for_each_file(fs::path p, F f)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fs::exists(p) && fs::is_directory(p))
|
||||
{
|
||||
for (auto i = fs::directory_iterator(p); i != fs::directory_iterator(); ++i)
|
||||
{
|
||||
auto ext = fs::extension(i->path());
|
||||
if (ext == ".input")
|
||||
{
|
||||
auto input_path = i->path();
|
||||
auto expect_path = input_path;
|
||||
expect_path.replace_extension(".expect");
|
||||
f(input_path, expect_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Directory: " << fs::absolute(p) << " does not exist." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
catch (const fs::filesystem_error& ex)
|
||||
{
|
||||
std::cerr << ex.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::string load(fs::path p)
|
||||
{
|
||||
boost::filesystem::ifstream file(p);
|
||||
if (!file)
|
||||
return "";
|
||||
std::string contents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
return contents;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline bool compare(
|
||||
fs::path input_path, fs::path expect_path
|
||||
, F f
|
||||
, char const* re_prefix
|
||||
, char const* re_suffix
|
||||
)
|
||||
{
|
||||
std::string output = f(load(input_path), input_path);
|
||||
std::string expected = load(expect_path);
|
||||
|
||||
auto result = compare(output, expected, re_prefix, re_suffix);
|
||||
if (!result.full_match)
|
||||
{
|
||||
std::cout << "=============================================" << std::endl;
|
||||
std::cout << "==== Mismatch Found:" << std::endl;
|
||||
int line = 1;
|
||||
int col = 1;
|
||||
for (auto i = output.begin(); i != result.pos; ++i)
|
||||
{
|
||||
if (*i == '\n')
|
||||
{
|
||||
line++;
|
||||
col = 0;
|
||||
}
|
||||
++col;
|
||||
}
|
||||
|
||||
std::cerr
|
||||
<< "==== File: " << expect_path
|
||||
<< ", Line: " << line
|
||||
<< ", Column: " << col
|
||||
<< std::endl;
|
||||
std::cerr << "=============================================" << std::endl;
|
||||
|
||||
// Print output
|
||||
std::cerr << output;
|
||||
std::cerr << "=============================================" << std::endl;
|
||||
std::cerr << "==== End" << std::endl;
|
||||
std::cerr << "=============================================" << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Copyright (c) 2014 Jamboree
|
||||
|
||||
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)
|
||||
//////////////////////////////////////////////////////////////////////////////*/
|
||||
#ifndef BOOST_SPIRIT_X3_UNREFCV_HPP_INCLUDED
|
||||
#define BOOST_SPIRIT_X3_UNREFCV_HPP_INCLUDED
|
||||
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
template <typename T>
|
||||
struct unrefcv : remove_cv<typename remove_reference<T>::type> {};
|
||||
|
||||
template <typename T>
|
||||
using unrefcv_t = typename unrefcv<T>::type;
|
||||
}}}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2014 Joel de Guzman
|
||||
Copyright (c) 2023 Nikita Kniazev
|
||||
|
||||
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)
|
||||
@@ -7,42 +8,62 @@
|
||||
#if !defined(BOOST_SPIRIT_X3_UC_TYPES_NOVEMBER_23_2008_0840PM)
|
||||
#define BOOST_SPIRIT_X3_UC_TYPES_NOVEMBER_23_2008_0840PM
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/regex/pending/unicode_iterator.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace x3
|
||||
{
|
||||
typedef ::boost::uint32_t ucs4_char;
|
||||
typedef char32_t ucs4_char;
|
||||
typedef char utf8_char;
|
||||
typedef std::basic_string<ucs4_char> ucs4_string;
|
||||
typedef std::basic_string<utf8_char> utf8_string;
|
||||
|
||||
namespace detail {
|
||||
inline void utf8_put_encode(utf8_string& out, ucs4_char x)
|
||||
{
|
||||
// https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf D90
|
||||
if (BOOST_UNLIKELY(x > 0x10FFFFul || (0xD7FFul < x && x < 0xE000ul)))
|
||||
x = 0xFFFDul;
|
||||
|
||||
// Table 3-6. UTF-8 Bit Distribution
|
||||
if (x < 0x80ul) {
|
||||
out.push_back(static_cast<unsigned char>(x));
|
||||
}
|
||||
else if (x < 0x800ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xC0ul + (x >> 6)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else if (x < 0x10000ul) {
|
||||
out.push_back(static_cast<unsigned char>(0xE0ul + (x >> 12)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
else {
|
||||
out.push_back(static_cast<unsigned char>(0xF0ul + (x >> 18)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 12) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + ((x >> 6) & 0x3Ful)));
|
||||
out.push_back(static_cast<unsigned char>(0x80ul + (x & 0x3Ful)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline utf8_string to_utf8(Char value)
|
||||
{
|
||||
// always store as UTF8
|
||||
utf8_string result;
|
||||
typedef std::back_insert_iterator<utf8_string> insert_iter;
|
||||
insert_iter out_iter(result);
|
||||
utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
typedef typename make_unsigned<Char>::type UChar;
|
||||
*utf8_iter = (UChar)value;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline utf8_string to_utf8(Char const* str)
|
||||
{
|
||||
// always store as UTF8
|
||||
utf8_string result;
|
||||
typedef std::back_insert_iterator<utf8_string> insert_iter;
|
||||
insert_iter out_iter(result);
|
||||
utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
typedef typename make_unsigned<Char>::type UChar;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
while (*str)
|
||||
*utf8_iter++ = (UChar)*str++;
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(*str++));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -50,46 +71,49 @@ namespace boost { namespace spirit { namespace x3
|
||||
inline utf8_string
|
||||
to_utf8(std::basic_string<Char, Traits, Allocator> const& str)
|
||||
{
|
||||
// always store as UTF8
|
||||
utf8_string result;
|
||||
typedef std::back_insert_iterator<utf8_string> insert_iter;
|
||||
insert_iter out_iter(result);
|
||||
utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
typedef typename make_unsigned<Char>::type UChar;
|
||||
typedef typename std::make_unsigned<Char>::type UChar;
|
||||
for (Char ch : str)
|
||||
{
|
||||
*utf8_iter++ = (UChar)ch;
|
||||
}
|
||||
detail::utf8_put_encode(result, static_cast<UChar>(ch));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Assume wchar_t content is UTF-16 on Windows and UCS-4 on Unix
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
// Assume wchar_t content is UTF-16 on MSVC, or mingw/wineg++ with -fshort-wchar
|
||||
#if defined(_MSC_VER) || defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2
|
||||
inline utf8_string to_utf8(wchar_t value)
|
||||
{
|
||||
utf8_string result;
|
||||
typedef std::back_insert_iterator<utf8_string> insert_iter;
|
||||
insert_iter out_iter(result);
|
||||
utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
|
||||
u16_to_u32_iterator<wchar_t const*, ucs4_char> ucs4_iter(&value);
|
||||
*utf8_iter++ = *ucs4_iter;
|
||||
|
||||
detail::utf8_put_encode(result, static_cast<std::make_unsigned<wchar_t>::type>(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline ucs4_char decode_utf16(wchar_t const*& s)
|
||||
{
|
||||
typedef std::make_unsigned<wchar_t>::type uwchar_t;
|
||||
|
||||
uwchar_t x(*s);
|
||||
if (x < 0xD800ul || x > 0xDFFFul)
|
||||
return x;
|
||||
|
||||
// expected high-surrogate
|
||||
if (BOOST_UNLIKELY((x >> 10) != 0b110110ul))
|
||||
return 0xFFFDul;
|
||||
|
||||
uwchar_t y(*++s);
|
||||
// expected low-surrogate
|
||||
if (BOOST_UNLIKELY((y >> 10) != 0b110111ul))
|
||||
return 0xFFFDul;
|
||||
|
||||
return ((x & 0x3FFul) << 10) + (y & 0x3FFul) + 0x10000ul;
|
||||
}
|
||||
}
|
||||
|
||||
inline utf8_string to_utf8(wchar_t const* str)
|
||||
{
|
||||
utf8_string result;
|
||||
typedef std::back_insert_iterator<utf8_string> insert_iter;
|
||||
insert_iter out_iter(result);
|
||||
utf8_output_iterator<insert_iter> utf8_iter(out_iter);
|
||||
|
||||
u16_to_u32_iterator<wchar_t const*, ucs4_char> ucs4_iter(str);
|
||||
for (ucs4_char c; (c = *ucs4_iter) != ucs4_char(); ++ucs4_iter) {
|
||||
*utf8_iter++ = c;
|
||||
}
|
||||
|
||||
for (ucs4_char c; (c = detail::decode_utf16(str)) != ucs4_char(); ++str)
|
||||
detail::utf8_put_encode(result, c);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user