stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,424 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM)
#define BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/bool_policies.hpp>
#include <boost/spirit/home/karma/numeric/detail/bool_utils.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
namespace karma
{
///////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename T>
struct bool_policies;
///////////////////////////////////////////////////////////////////////
// This is the class that the user can instantiate directly in
// order to create a customized bool generator
template <typename T = bool, typename Policies = bool_policies<T> >
struct bool_generator
: spirit::terminal<tag::stateful_tag<Policies, tag::bool_, T> >
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
bool_generator() {}
bool_generator(Policies const& data)
: spirit::terminal<tag_type>(data) {}
};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::bool_> // enables bool_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::true_> // enables true_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::false_> // enables false_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, bool> // enables lit(true)
: mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables bool_(...)
, terminal_ex<tag::bool_, fusion::vector1<A0> >
> : mpl::true_ {};
template <> // enables *lazy* bool_(...)
struct use_lazy_terminal<karma::domain, tag::bool_, 1>
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// enables any custom bool_generator
template <typename Policies, typename T>
struct use_terminal<karma::domain
, tag::stateful_tag<Policies, tag::bool_, T> >
: mpl::true_ {};
// enables any custom bool_generator(...)
template <typename Policies, typename T, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
, fusion::vector1<A0> > >
: mpl::true_ {};
// enables *lazy* custom bool_generator
template <typename Policies, typename T>
struct use_lazy_terminal<karma::domain
, tag::stateful_tag<Policies, tag::bool_, T>, 1>
: mpl::true_ {};
// enables lit(bool)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_bool<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::bool_;
using spirit::true_;
using spirit::false_;
using spirit::lit; // lit(true) is equivalent to true
#endif
using spirit::bool_type;
using spirit::true_type;
using spirit::false_type;
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for bool generators not having a direct
// initializer: bool_. These generators must be used in conjunction with
// an Attribute.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag, typename Policies>
struct any_bool_generator
: primitive_generator<any_bool_generator<T, CharEncoding, Tag, Policies> >
{
public:
any_bool_generator(Policies const& p = Policies())
: p_(p) {}
typedef typename Policies::properties properties;
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// bool_ has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr) const
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return bool_inserter<T, Policies, CharEncoding, Tag>::call(
sink, traits::extract_from<T>(attr, context), p_) &&
delimit_out(sink, d); // always do post-delimiting
}
// this bool_ has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use boolean generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, bool_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("bool");
}
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for bool generators having a direct
// initializer: bool_(true), bool_(0) etc.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag
, typename Policies, bool no_attribute>
struct literal_bool_generator
: primitive_generator<literal_bool_generator<T, CharEncoding, Tag
, Policies, no_attribute> >
{
public:
typedef typename Policies::properties properties;
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_bool_generator(typename add_const<T>::type n
, Policies const& p = Policies())
: n_(n), p_(p) {}
// A bool_() which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
bool(n_) != bool(traits::extract_from<attribute_type>(attr, context)))
{
return false;
}
return bool_inserter<T, Policies, CharEncoding, Tag>::
call(sink, n_, p_) && delimit_out(sink, d);
}
// A bool_() without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return bool_inserter<T, Policies, CharEncoding, Tag>::
call(sink, n_) && delimit_out(sink, d);
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("bool");
}
T n_;
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers, typename T = bool
, typename Policies = bool_policies<T> >
struct make_bool
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_bool_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Policies
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term));
}
};
template <typename Modifiers, bool b>
struct make_bool_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, false
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type(b);
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::bool_, Modifiers>
: detail::make_bool<Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::true_, Modifiers>
: detail::make_bool_literal<Modifiers, true> {};
template <typename Modifiers>
struct make_primitive<tag::false_, Modifiers>
: detail::make_bool_literal<Modifiers, false> {};
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
: detail::make_bool<Modifiers
, typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers, typename T = bool
, typename Policies = bool_policies<T> >
struct make_bool_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Policies, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(fusion::at_c<0>(term.args)
, get_stateful_data<tag_type>::call(term.term));
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::bool_, fusion::vector1<A0> >, Modifiers>
: detail::make_bool_direct<Modifiers> {};
template <typename T, typename Policies, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
, fusion::vector1<A0> >
, Modifiers>
: detail::make_bool_direct<Modifiers
, typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers>
struct basic_bool_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
template <typename Modifiers>
struct make_primitive<bool, Modifiers>
: detail::basic_bool_literal<Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_bool<A0> >::type>
: detail::basic_bool_literal<Modifiers>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif
@@ -0,0 +1,117 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_POLICIES_SEP_28_2009_1203PM)
#define BOOST_SPIRIT_KARMA_BOOL_POLICIES_SEP_28_2009_1203PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// bool_policies, if you need special handling of your boolean output
// just overload this policy class and use it as a template
// parameter to the karma::bool_generator boolean generator
//
// struct special_bool_policy : karma::bool_policies<>
// {
// // we want to spell the names of false as eurt (true backwards)
// template <typename CharEncoding, typename Tag
// , typename OutputIterator>
// static bool generate_false(OutputIterator& sink, bool)
// {
// return string_inserter<CharEncoding, Tag>::call(sink, "eurt");
// }
// };
//
// typedef karma::bool_generator<special_bool_policy> backwards_bool;
//
// karma::generate(sink, backwards_bool(), false); // will output: eurt
//
///////////////////////////////////////////////////////////////////////////
template <typename T = bool>
struct bool_policies
{
///////////////////////////////////////////////////////////////////////
// Expose the data type the generator is targeted at
///////////////////////////////////////////////////////////////////////
typedef T value_type;
///////////////////////////////////////////////////////////////////////
// By default the policy doesn't require any special iterator
// functionality. The boolean generator exposes its properties
// from here, so this needs to be updated in case other properties
// need to be implemented.
///////////////////////////////////////////////////////////////////////
typedef mpl::int_<generator_properties::no_properties> properties;
///////////////////////////////////////////////////////////////////////
// This is the main function used to generate the output for a
// boolean. It is called by the boolean generator in order
// to perform the conversion. In theory all of the work can be
// implemented here, but it is the easiest to use existing
// functionality provided by the type specified by the template
// parameter `Inserter`.
//
// sink: the output iterator to use for generation
// n: the floating point number to convert
// p: the instance of the policy type used to instantiate this
// floating point generator.
///////////////////////////////////////////////////////////////////////
template <typename Inserter, typename OutputIterator, typename Policies>
static bool
call (OutputIterator& sink, T n, Policies const& p)
{
return Inserter::call_n(sink, n, p);
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations of a true boolean value
//
// sink The output iterator to use for generation
// b The boolean value to convert.
//
// The CharEncoding and Tag template parameters are either of the type
// unused_type or describes the character class and conversion to be
// applied to any output possibly influenced by either the lower[...]
// or upper[...] directives.
//
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool generate_true(OutputIterator& sink, T)
{
return string_inserter<CharEncoding, Tag>::call(sink, "true");
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations of a false boolean value
//
// sink The output iterator to use for generation
// b The boolean value to convert.
//
// The CharEncoding and Tag template parameters are either of the type
// unused_type or describes the character class and conversion to be
// applied to any output possibly influenced by either the lower[...]
// or upper[...] directives.
//
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool generate_false(OutputIterator& sink, T)
{
return string_inserter<CharEncoding, Tag>::call(sink, "false");
}
};
}}}
#endif
@@ -0,0 +1,67 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_UTILS_SEP_28_2009_0644PM)
#define BOOST_SPIRIT_KARMA_BOOL_UTILS_SEP_28_2009_0644PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/detail/workaround.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The bool_inserter template takes care of the boolean to string
// conversion. The Policies template parameter is used to allow
// customization of the formatting process
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct bool_policies;
template <typename T
, typename Policies = bool_policies<T>
, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct bool_inserter
{
template <typename OutputIterator, typename U>
static bool
call (OutputIterator& sink, U b, Policies const& p = Policies())
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
p; // suppresses warning: C4100: 'p' : unreferenced formal parameter
#endif
return p.template call<bool_inserter>(sink, T(b), p);
}
///////////////////////////////////////////////////////////////////////
// This is the workhorse behind the real generator
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename U>
static bool
call_n (OutputIterator& sink, U b, Policies const& p)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
p; // suppresses warning: C4100: 'p' : unreferenced formal parameter
#endif
if (b)
return p.template generate_true<CharEncoding, Tag>(sink, b);
return p.template generate_false<CharEncoding, Tag>(sink, b);
}
};
}}}
#endif
@@ -0,0 +1,774 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
#define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/detail/pow10.hpp>
#include <boost/spirit/home/support/detail/sign.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
// integer string generation loop (see below).
//
// Set the value to some integer in between 0 (no unrolling) and the
// largest expected generated integer string length (complete unrolling).
// If not specified, this value defaults to 6.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
#define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
#endif
#if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
#error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a non-negative value!"
#endif
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////
//
// return the absolute value from a given number, avoiding over- and
// underflow
//
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct absolute_value
{
typedef T type;
static T call (T n)
{
// allow for ADL to find the correct overloads for fabs
using namespace std;
return fabs(n);
}
};
#define BOOST_SPIRIT_ABSOLUTE_VALUE(signedtype, unsignedtype) \
template <> \
struct absolute_value<signedtype> \
{ \
typedef unsignedtype type; \
static type call(signedtype n) \
{ \
return (n >= 0) ? n : (unsignedtype)(-n); \
} \
} \
/**/
#define BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsignedtype) \
template <> \
struct absolute_value<unsignedtype> \
{ \
typedef unsignedtype type; \
static type call(unsignedtype n) \
{ \
return n; \
} \
} \
/**/
BOOST_SPIRIT_ABSOLUTE_VALUE(signed char, unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE(char, unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE(short, unsigned short);
BOOST_SPIRIT_ABSOLUTE_VALUE(int, unsigned int);
BOOST_SPIRIT_ABSOLUTE_VALUE(long, unsigned long);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned short);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned int);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned long);
#ifdef BOOST_HAS_LONG_LONG
BOOST_SPIRIT_ABSOLUTE_VALUE(boost::long_long_type, boost::ulong_long_type);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(boost::ulong_long_type);
#endif
#undef BOOST_SPIRIT_ABSOLUTE_VALUE
#undef BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED
template <>
struct absolute_value<float>
{
typedef float type;
static type call(float n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
template <>
struct absolute_value<double>
{
typedef double type;
static type call(double n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
template <>
struct absolute_value<long double>
{
typedef long double type;
static type call(long double n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
// specialization for pointers
template <typename T>
struct absolute_value<T*>
{
typedef std::size_t type;
static type call (T* p)
{
return std::size_t(p);
}
};
template <typename T>
inline typename absolute_value<T>::type
get_absolute_value(T n)
{
return absolute_value<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_negative
{
static bool call(T n)
{
return (n < 0) ? true : false;
}
};
template <>
struct is_negative<float>
{
static bool call(float n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <>
struct is_negative<double>
{
static bool call(double n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <>
struct is_negative<long double>
{
static bool call(long double n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <typename T>
inline bool test_negative(T n)
{
return is_negative<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_zero
{
static bool call(T n)
{
return (n == 0) ? true : false;
}
};
template <>
struct is_zero<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <>
struct is_zero<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <>
struct is_zero<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <typename T>
inline bool test_zero(T n)
{
return is_zero<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_nan
{
static bool call(T n)
{
// NaN numbers are not equal to anything
return (n != n) ? true : false;
}
};
template <>
struct is_nan<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <>
struct is_nan<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <>
struct is_nan<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <typename T>
inline bool test_nan(T n)
{
return is_nan<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_infinite
{
static bool call(T n)
{
if (!std::numeric_limits<T>::has_infinity)
return false;
return (n == std::numeric_limits<T>::infinity()) ? true : false;
}
};
template <>
struct is_infinite<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <>
struct is_infinite<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <>
struct is_infinite<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <typename T>
inline bool test_infinite(T n)
{
return is_infinite<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
struct cast_to_long
{
static long call(float n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
static long call(double n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
static long call(long double n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
template <typename T>
static long call(T n, mpl::false_)
{
// allow for ADL to find the correct overload for floor and
// lround
using namespace std;
return lround(floor(n));
}
template <typename T>
static long call(T n, mpl::true_)
{
return static_cast<long>(n);
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
struct truncate_to_long
{
static long call(float n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
static long call(double n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
static long call(long double n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
template <typename T>
static long call(T n, mpl::false_)
{
// allow for ADL to find the correct overloads for ltrunc
using namespace std;
return ltrunc(n);
}
template <typename T>
static long call(T n, mpl::true_)
{
return static_cast<long>(n);
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
//
// Traits class for radix specific number conversion
//
// Convert a digit from binary representation to character
// representation:
//
// static int call(unsigned n);
//
///////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename CharEncoding, typename Tag, bool radix_less_than_10>
struct convert_digit
{
static int call(unsigned n)
{
if (n <= 9)
return n + '0';
using spirit::char_class::convert;
return convert<CharEncoding>::to(Tag(), n - 10 + 'a');
}
};
template <>
struct convert_digit<unused_type, unused_type, false>
{
static int call(unsigned n)
{
if (n <= 9)
return n + '0';
return n - 10 + 'a';
}
};
template <typename CharEncoding, typename Tag>
struct convert_digit<CharEncoding, Tag, true>
{
static int call(unsigned n)
{
return n + '0';
}
};
}
template <unsigned Radix, typename CharEncoding, typename Tag>
struct convert_digit
: detail::convert_digit<CharEncoding, Tag, (Radix <= 10) ? true : false>
{};
///////////////////////////////////////////////////////////////////////
template <unsigned Radix>
struct divide
{
template <typename T>
static T call(T& n, mpl::true_)
{
return n / Radix;
}
template <typename T>
static T call(T& n, mpl::false_)
{
// Allow ADL to find the correct overload for floor
using namespace std;
return floor(n / Radix);
}
template <typename T>
static T call(T& n, T const&, int)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
template <typename T>
static T call(T& n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
// specialization for division by 10
template <>
struct divide<10>
{
template <typename T>
static T call(T& n, T, int, mpl::true_)
{
return n / 10;
}
template <typename T>
static T call(T, T& num, int exp, mpl::false_)
{
// Allow ADL to find the correct overload for floor
using namespace std;
return floor(num / spirit::traits::pow10<T>(exp));
}
template <typename T>
static T call(T& n, T& num, int exp)
{
return call(n, num, exp, mpl::bool_<is_integral<T>::value>());
}
template <typename T>
static T call(T& n)
{
return call(n, n, 1, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
template <unsigned Radix>
struct remainder
{
template <typename T>
static long call(T n, mpl::true_)
{
// this cast is safe since we know the result is not larger
// than Radix
return static_cast<long>(n % Radix);
}
template <typename T>
static long call(T n, mpl::false_)
{
// Allow ADL to find the correct overload for fmod
using namespace std;
return cast_to_long::call(fmod(n, T(Radix)));
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
}}}
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The int_inserter template takes care of the integer to string
// conversion. If specified, the loop is unrolled for better performance.
//
// Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
// between 0 (no unrolling) and the largest expected generated integer
// string length (complete unrolling).
// If not specified, this value defaults to 6.
//
///////////////////////////////////////////////////////////////////////////
#define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data) \
if (!traits::test_zero(n)) { \
int ch = radix_type::call(remainder_type::call(n)); \
n = divide_type::call(n, num, ++exp); \
/**/
#define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data) \
*sink = char(ch); \
++sink; \
} \
/**/
template <
unsigned Radix, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct int_inserter
{
typedef traits::convert_digit<Radix, CharEncoding, Tag> radix_type;
typedef traits::divide<Radix> divide_type;
typedef traits::remainder<Radix> remainder_type;
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T n, T& num, int exp)
{
// remainder_type::call returns n % Radix
int ch = radix_type::call(remainder_type::call(n));
n = divide_type::call(n, num, ++exp);
BOOST_PP_REPEAT(
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
if (!traits::test_zero(n))
call(sink, n, num, exp);
BOOST_PP_REPEAT(
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _);
*sink = char(ch);
++sink;
return true;
}
// Common code for integer string representations
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T n)
{
return call(sink, n, n, 0);
}
private:
// helper function returning the biggest number representable either in
// a boost::long_long_type (if this does exist) or in a plain long
// otherwise
#if defined(BOOST_HAS_LONG_LONG)
typedef boost::long_long_type biggest_long_type;
#else
typedef long biggest_long_type;
#endif
static biggest_long_type max_long()
{
return (std::numeric_limits<biggest_long_type>::max)();
}
public:
// Specialization for doubles and floats, falling back to long integers
// for representable values. These specializations speed up formatting
// of floating point numbers considerably as all the required
// arithmetics will be executed using integral data types.
template <typename OutputIterator>
static bool
call(OutputIterator& sink, long double n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, double n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, float n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
};
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
///////////////////////////////////////////////////////////////////////////
//
// The uint_inserter template takes care of the conversion of any integer
// to a string, while interpreting the number as an unsigned type.
//
///////////////////////////////////////////////////////////////////////////
template <
unsigned Radix, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct uint_inserter : int_inserter<Radix, CharEncoding, Tag>
{
typedef int_inserter<Radix, CharEncoding, Tag> base_type;
// Common code for integer string representations
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T const& n)
{
typedef typename traits::absolute_value<T>::type type;
type un = type(n);
return base_type::call(sink, un, un, 0);
}
};
///////////////////////////////////////////////////////////////////////////
//
// The sign_inserter template generates a sign for a given numeric value.
//
// The parameter forcesign allows to generate a sign even for positive
// numbers.
//
///////////////////////////////////////////////////////////////////////////
struct sign_inserter
{
template <typename OutputIterator>
static bool
call_noforce(OutputIterator& sink, bool is_zero, bool is_negative,
bool sign_if_zero)
{
// generate a sign for negative numbers only
if (is_negative || (is_zero && sign_if_zero)) {
*sink = '-';
++sink;
}
return true;
}
template <typename OutputIterator>
static bool
call_force(OutputIterator& sink, bool is_zero, bool is_negative,
bool sign_if_zero)
{
// generate a sign for all numbers except zero
if (!is_zero || sign_if_zero)
*sink = is_negative ? '-' : '+';
else
*sink = ' ';
++sink;
return true;
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, bool is_zero, bool is_negative
, bool forcesign, bool sign_if_zero = false)
{
return forcesign ?
call_force(sink, is_zero, is_negative, sign_if_zero) :
call_noforce(sink, is_zero, is_negative, sign_if_zero);
}
};
///////////////////////////////////////////////////////////////////////////
// These are helper functions for the real policies allowing to generate
// a single character and a string
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding = unused_type, typename Tag = unused_type>
struct char_inserter
{
template <typename OutputIterator, typename Char>
static bool call(OutputIterator& sink, Char c)
{
return detail::generate_to(sink, c, CharEncoding(), Tag());
}
};
template <typename CharEncoding = unused_type, typename Tag = unused_type>
struct string_inserter
{
template <typename OutputIterator, typename String>
static bool call(OutputIterator& sink, String str)
{
return detail::string_generate(sink, str, CharEncoding(), Tag());
}
};
}}}
#endif
@@ -0,0 +1,187 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM)
#define BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/limits.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/detail/pow10.hpp>
#include <boost/spirit/home/support/detail/sign.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The real_inserter template takes care of the floating point number to
// string conversion. The Policies template parameter is used to allow
// customization of the formatting process
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_policies;
template <typename T
, typename Policies = real_policies<T>
, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct real_inserter
{
template <typename OutputIterator, typename U>
static bool
call (OutputIterator& sink, U n, Policies const& p = Policies())
{
if (traits::test_nan(n)) {
return p.template nan<CharEncoding, Tag>(
sink, n, p.force_sign(n));
}
else if (traits::test_infinite(n)) {
return p.template inf<CharEncoding, Tag>(
sink, n, p.force_sign(n));
}
return p.template call<real_inserter>(sink, n, p);
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(push)
# pragma warning(disable: 4100) // 'p': unreferenced formal parameter
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4267) // conversion from 'size_t' to 'unsigned int', possible loss of data
#endif
///////////////////////////////////////////////////////////////////////
// This is the workhorse behind the real generator
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename U>
static bool
call_n (OutputIterator& sink, U n, Policies const& p)
{
// prepare sign and get output format
bool force_sign = p.force_sign(n);
bool sign_val = false;
int flags = p.floatfield(n);
if (traits::test_negative(n))
{
n = -n;
sign_val = true;
}
// The scientific representation requires the normalization of the
// value to convert.
// get correct precision for generated number
unsigned precision = p.precision(n);
if (std::numeric_limits<U>::digits10)
{
// limit generated precision to digits10, if defined
precision = (std::min)(precision,
(unsigned)std::numeric_limits<U>::digits10 + 1);
}
// allow for ADL to find the correct overloads for log10 et.al.
using namespace std;
U dim = 0;
if (0 == (Policies::fmtflags::fixed & flags) && !traits::test_zero(n))
{
dim = log10(n);
if (dim > 0)
n /= spirit::traits::pow10<U>(traits::truncate_to_long::call(dim));
else if (n < 1.) {
long exp = traits::truncate_to_long::call(-dim);
if (exp != -dim)
++exp;
dim = static_cast<U>(-exp);
n *= spirit::traits::pow10<U>(exp);
}
}
// prepare numbers (sign, integer and fraction part)
U integer_part;
U precexp = spirit::traits::pow10<U>(precision);
U fractional_part = modf(n, &integer_part);
fractional_part = floor(fractional_part * precexp + U(0.5));
if (fractional_part >= precexp)
{
fractional_part = floor(fractional_part - precexp);
integer_part += 1; // handle rounding overflow
}
// if trailing zeros are to be omitted, normalize the precision and
// fractional part
U long_int_part = floor(integer_part);
U long_frac_part = fractional_part;
unsigned prec = precision;
if (!p.trailing_zeros(n))
{
U frac_part_floor = long_frac_part;
if (0 != long_frac_part) {
// remove the trailing zeros
while (0 != prec &&
0 == traits::remainder<10>::call(long_frac_part))
{
long_frac_part = traits::divide<10>::call(long_frac_part);
--prec;
}
}
else {
// if the fractional part is zero, we don't need to output
// any additional digits
prec = 0;
}
if (precision != prec)
{
long_frac_part = frac_part_floor /
spirit::traits::pow10<U>(precision-prec);
}
}
// call the actual generating functions to output the different parts
if ((force_sign || sign_val) &&
traits::test_zero(long_int_part) &&
traits::test_zero(long_frac_part))
{
sign_val = false; // result is zero, no sign please
force_sign = false;
}
// generate integer part
bool r = p.integer_part(sink, long_int_part, sign_val, force_sign);
// generate decimal point
r = r && p.dot(sink, long_frac_part, precision);
// generate fractional part with the desired precision
r = r && p.fraction_part(sink, long_frac_part, prec, precision);
if (r && 0 == (Policies::fmtflags::fixed & flags)) {
return p.template exponent<CharEncoding, Tag>(sink,
traits::truncate_to_long::call(dim));
}
return r;
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(pop)
#endif
};
}}}
#endif
@@ -0,0 +1,525 @@
// Copyright (c) 2001-2012 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)
#if !defined(BOOST_SPIRIT_KARMA_INT_FEB_23_2007_0840PM)
#define BOOST_SPIRIT_KARMA_INT_FEB_23_2007_0840PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
namespace tag
{
template <typename T, unsigned Radix, bool force_sign>
struct int_generator
{
BOOST_SPIRIT_IS_TAG()
};
}
namespace karma
{
///////////////////////////////////////////////////////////////////////
// This one is the class that the user can instantiate directly in
// order to create a customized int generator
template <typename T = int, unsigned Radix = 10, bool force_sign = false>
struct int_generator
: spirit::terminal<tag::int_generator<T, Radix, force_sign> >
{};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::short_> // enables short_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::int_> // enables int_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::long_> // enables long_
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, tag::long_long> // enables long_long
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, short> // enables lit(short(0))
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, int> // enables lit(0)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, long> // enables lit(0L)
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, boost::long_long_type> // enables lit(0LL)
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables short_(...)
, terminal_ex<tag::short_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables int_(...)
, terminal_ex<tag::int_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables long_(...)
, terminal_ex<tag::long_, fusion::vector1<A0> >
> : mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <typename A0>
struct use_terminal<karma::domain // enables long_long(...)
, terminal_ex<tag::long_long, fusion::vector1<A0> >
> : mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <> // enables *lazy* short_(...)
struct use_lazy_terminal<karma::domain, tag::short_, 1>
: mpl::true_ {};
template <> // enables *lazy* int_(...)
struct use_lazy_terminal<karma::domain, tag::int_, 1>
: mpl::true_ {};
template <> // enables *lazy* long_(...)
struct use_lazy_terminal<karma::domain, tag::long_, 1>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables *lazy* long_long(...)
struct use_lazy_terminal<karma::domain, tag::long_long, 1>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
// enables any custom int_generator
template <typename T, unsigned Radix, bool force_sign>
struct use_terminal<karma::domain, tag::int_generator<T, Radix, force_sign> >
: mpl::true_ {};
// enables any custom int_generator(...)
template <typename T, unsigned Radix, bool force_sign, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::int_generator<T, Radix, force_sign>
, fusion::vector1<A0> >
> : mpl::true_ {};
// enables *lazy* custom int_generator
template <typename T, unsigned Radix, bool force_sign>
struct use_lazy_terminal<
karma::domain
, tag::int_generator<T, Radix, force_sign>
, 1 // arity
> : mpl::true_ {};
// enables lit(int)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_int<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::short_;
using spirit::int_;
using spirit::long_;
#ifdef BOOST_HAS_LONG_LONG
using spirit::long_long;
#endif
using spirit::lit; // lit(1) is equivalent to 1
#endif
using spirit::short_type;
using spirit::int_type;
using spirit::long_type;
#ifdef BOOST_HAS_LONG_LONG
using spirit::long_long_type;
#endif
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for int generators not having a direct
// initializer: int_, long_ etc. These generators must be used in
// conjunction with an Attribute.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool force_sign>
struct any_int_generator
: primitive_generator<any_int_generator<T, CharEncoding, Tag, Radix
, force_sign> >
{
private:
template <typename OutputIterator, typename Attribute>
static bool insert_int(OutputIterator& sink, Attribute const& attr)
{
return sign_inserter::call(sink, traits::test_zero(attr)
, traits::test_negative(attr), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, traits::get_absolute_value(attr));
}
public:
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
signed_unsigned_mismatch, ());
// int has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr)
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return insert_int(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
// this int has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, int_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("integer");
}
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for int generators having a direct
// initializer: int_(10), long_(20) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool force_sign, bool no_attribute>
struct literal_int_generator
: primitive_generator<literal_int_generator<T, CharEncoding, Tag, Radix
, force_sign, no_attribute> >
{
private:
template <typename OutputIterator, typename Attribute>
static bool insert_int(OutputIterator& sink, Attribute const& attr)
{
return sign_inserter::call(sink, traits::test_zero(attr)
, traits::test_negative(attr), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, traits::get_absolute_value(attr));
}
public:
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_int_generator(typename add_const<T>::type n)
: n_(n) {}
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
signed_unsigned_mismatch, ());
// A int_(1) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
return insert_int(sink, n_) && delimit_out(sink, d);
}
// A int_(1) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return insert_int(sink, n_) && delimit_out(sink, d);
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("integer");
}
T n_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10
, bool force_sign = false>
struct make_int
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix
, force_sign
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::short_, Modifiers>
: detail::make_int<short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::int_, Modifiers>
: detail::make_int<int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::long_, Modifiers>
: detail::make_int<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<tag::long_long, Modifiers>
: detail::make_int<boost::long_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, bool force_sign, typename Modifiers>
struct make_primitive<tag::int_generator<T, Radix, force_sign>, Modifiers>
: detail::make_int<typename remove_const<T>::type
, Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10
, bool force_sign = false>
struct make_int_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix, force_sign, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::short_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<short, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::int_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<int, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_long, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<boost::long_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, bool force_sign, typename A0
, typename Modifiers>
struct make_primitive<
terminal_ex<tag::int_generator<T, Radix, force_sign>
, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<typename remove_const<T>::type
, Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_int_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, false, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
template <typename Modifiers>
struct make_primitive<short, Modifiers>
: detail::basic_int_literal<short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<int, Modifiers>
: detail::basic_int_literal<int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<long, Modifiers>
: detail::basic_int_literal<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<boost::long_long_type, Modifiers>
: detail::basic_int_literal<boost::long_long_type, Modifiers> {};
#endif
// lit(int)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_int<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, false, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif
@@ -0,0 +1,454 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
#define BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/real_policies.hpp>
#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
namespace boost { namespace spirit
{
namespace karma
{
///////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename T>
struct real_policies;
///////////////////////////////////////////////////////////////////////
// This is the class that the user can instantiate directly in
// order to create a customized real generator
template <typename T = double, typename Policies = real_policies<T> >
struct real_generator
: spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> >
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
real_generator() {}
real_generator(Policies const& p)
: spirit::terminal<tag_type>(p) {}
};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::float_> // enables float_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::double_> // enables double_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::long_double> // enables long_double
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, float> // enables lit(1.0f)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, double> // enables lit(1.0)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, long double> // enables lit(1.0l)
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables float_(...)
, terminal_ex<tag::float_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables double_(...)
, terminal_ex<tag::double_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables long_double(...)
, terminal_ex<tag::long_double, fusion::vector1<A0> >
> : mpl::true_ {};
// lazy float_(...), double_(...), long_double(...)
template <>
struct use_lazy_terminal<karma::domain, tag::float_, 1>
: mpl::true_ {};
template <>
struct use_lazy_terminal<karma::domain, tag::double_, 1>
: mpl::true_ {};
template <>
struct use_lazy_terminal<karma::domain, tag::long_double, 1>
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// enables custom real generator
template <typename T, typename Policies>
struct use_terminal<karma::domain
, tag::stateful_tag<Policies, tag::double_, T> >
: mpl::true_ {};
template <typename T, typename Policies, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
, fusion::vector1<A0> > >
: mpl::true_ {};
// enables *lazy* custom real generator
template <typename T, typename Policies>
struct use_lazy_terminal<
karma::domain
, tag::stateful_tag<Policies, tag::double_, T>
, 1 // arity
> : mpl::true_ {};
// enables lit(double)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_real<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::float_;
using spirit::double_;
using spirit::long_double;
#endif
using spirit::float_type;
using spirit::double_type;
using spirit::long_double_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for real generators not having a direct
// initializer: float_, double_ etc. These generators must be used in
// conjunction with an attribute.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename Policies, typename CharEncoding, typename Tag>
struct any_real_generator
: primitive_generator<any_real_generator<T, Policies, CharEncoding, Tag> >
{
typedef typename Policies::properties properties;
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
any_real_generator(Policies const& policies = Policies())
: p_(policies) {}
// double_/float_/etc. has an attached attribute
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, traits::extract_from<T>(attr, context), p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// this double_/float_/etc. has no attribute attached, it needs to have
// been initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool generate(OutputIterator&, Context&, Delimiter const&
, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, real_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("real");
}
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for real generators having a direct
// initializer: float_(10.), double_(20.) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename Policies, typename CharEncoding, typename Tag
, bool no_attribute>
struct literal_real_generator
: primitive_generator<literal_real_generator<T, Policies, CharEncoding
, Tag, no_attribute> >
{
typedef typename Policies::properties properties;
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_real_generator(typename add_const<T>::type n
, Policies const& policies = Policies())
: n_(n), p_(policies) {}
// A double_(1.0) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, n_, p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// A double_(1.0) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, n_, p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("real");
}
T n_;
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers
, typename Policies = real_policies<T> >
struct make_real
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_real_generator<
T, Policies
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term));
}
};
}
template <typename Modifiers>
struct make_primitive<tag::float_, Modifiers>
: detail::make_real<float, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::double_, Modifiers>
: detail::make_real<double, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::long_double, Modifiers>
: detail::make_real<long double, Modifiers> {};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::double_, T>, Modifiers>
: detail::make_real<typename remove_const<T>::type
, Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers
, typename Policies = real_policies<T> >
struct make_real_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
T, Policies
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(T(fusion::at_c<0>(term.args))
, get_stateful_data<tag_type>::call(term.term));
}
};
}
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::float_, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<float, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::double_, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<double, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_double, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<long double, Modifiers> {};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Policies, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
, fusion::vector1<A0> >
, Modifiers>
: detail::make_real_direct<typename remove_const<T>::type
, Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_real_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
T, real_policies<T>
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(T(i));
}
};
}
template <typename Modifiers>
struct make_primitive<float, Modifiers>
: detail::basic_real_literal<float, Modifiers> {};
template <typename Modifiers>
struct make_primitive<double, Modifiers>
: detail::basic_real_literal<double, Modifiers> {};
template <typename Modifiers>
struct make_primitive<long double, Modifiers>
: detail::basic_real_literal<long double, Modifiers> {};
// lit(double)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_real<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
typename remove_const<A0>::type, real_policies<A0>
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif // defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
@@ -0,0 +1,334 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
#define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/int.hpp>
#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// real_policies, if you need special handling of your floating
// point numbers, just overload this policy class and use it as a template
// parameter to the karma::real_generator floating point specifier:
//
// template <typename T>
// struct scientific_policy : karma::real_policies<T>
// {
// // we want the numbers always to be in scientific format
// static int floatfield(T n) { return fmtflags::scientific; }
// };
//
// typedef
// karma::real_generator<double, scientific_policy<double> >
// science_type;
//
// karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_policies
{
///////////////////////////////////////////////////////////////////////
// Expose the data type the generator is targeted at
///////////////////////////////////////////////////////////////////////
typedef T value_type;
///////////////////////////////////////////////////////////////////////
// By default the policy doesn't require any special iterator
// functionality. The floating point generator exposes its properties
// from here, so this needs to be updated in case other properties
// need to be implemented.
///////////////////////////////////////////////////////////////////////
typedef mpl::int_<generator_properties::no_properties> properties;
///////////////////////////////////////////////////////////////////////
// Specifies, which representation type to use during output
// generation.
///////////////////////////////////////////////////////////////////////
struct fmtflags
{
enum {
scientific = 0, // Generate floating-point values in scientific
// format (with an exponent field).
fixed = 1 // Generate floating-point values in fixed-point
// format (with no exponent field).
};
};
///////////////////////////////////////////////////////////////////////
// This is the main function used to generate the output for a
// floating point number. It is called by the real generator in order
// to perform the conversion. In theory all of the work can be
// implemented here, but it is the easiest to use existing
// functionality provided by the type specified by the template
// parameter `Inserter`.
//
// sink: the output iterator to use for generation
// n: the floating point number to convert
// p: the instance of the policy type used to instantiate this
// floating point generator.
///////////////////////////////////////////////////////////////////////
template <typename Inserter, typename OutputIterator, typename Policies>
static bool
call (OutputIterator& sink, T n, Policies const& p)
{
return Inserter::call_n(sink, n, p);
}
///////////////////////////////////////////////////////////////////////
// The default behavior is to not to require generating a sign. If
// 'force_sign()' returns true, then all generated numbers will
// have a sign ('+' or '-', zeros will have a space instead of a sign)
//
// n The floating point number to output. This can be used to
// adjust the required behavior depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static bool force_sign(T)
{
return false;
}
///////////////////////////////////////////////////////////////////////
// Return whether trailing zero digits have to be emitted in the
// fractional part of the output. If set, this flag instructs the
// floating point generator to emit trailing zeros up to the required
// precision digits (as returned by the precision() function).
//
// n The floating point number to output. This can be used to
// adjust the required behavior depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static bool trailing_zeros(T)
{
// the default behavior is not to generate trailing zeros
return false;
}
///////////////////////////////////////////////////////////////////////
// Decide, which representation type to use in the generated output.
//
// By default all numbers having an absolute value of zero or in
// between 0.001 and 100000 will be generated using the fixed format,
// all others will be generated using the scientific representation.
//
// The function trailing_zeros() can be used to force the output of
// trailing zeros in the fractional part up to the number of digits
// returned by the precision() member function. The default is not to
// generate the trailing zeros.
//
// n The floating point number to output. This can be used to
// adjust the formatting flags depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static int floatfield(T n)
{
if (traits::test_zero(n))
return fmtflags::fixed;
T abs_n = traits::get_absolute_value(n);
return (abs_n >= 1e5 || abs_n < 1e-3)
? fmtflags::scientific : fmtflags::fixed;
}
///////////////////////////////////////////////////////////////////////
// Return the maximum number of decimal digits to generate in the
// fractional part of the output.
//
// n The floating point number to output. This can be used to
// adjust the required precision depending on the value of
// this number. If the trailing zeros flag is specified the
// fractional part of the output will be 'filled' with
// zeros, if appropriate
//
// Note: If the trailing_zeros flag is not in effect additional
// comments apply. See the comment for the fraction_part()
// function below. Moreover, this precision will be limited
// to the value of std::numeric_limits<T>::digits10 + 1
///////////////////////////////////////////////////////////////////////
static unsigned precision(T)
{
// by default, generate max. 3 fractional digits
return 3;
}
///////////////////////////////////////////////////////////////////////
// Generate the integer part of the number.
//
// sink The output iterator to use for generation
// n The absolute value of the integer part of the floating
// point number to convert (always non-negative).
// sign The sign of the overall floating point number to
// convert.
// force_sign Whether a sign has to be generated even for
// non-negative numbers. Note, that force_sign will be
// set to false for zero floating point values.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool integer_part (OutputIterator& sink, T n, bool sign
, bool force_sign)
{
return sign_inserter::call(
sink, traits::test_zero(n), sign, force_sign, force_sign) &&
int_inserter<10>::call(sink, n);
}
///////////////////////////////////////////////////////////////////////
// Generate the decimal point.
//
// sink The output iterator to use for generation
// n The fractional part of the floating point number to
// convert. Note that this number is scaled such, that
// it represents the number of units which correspond
// to the value returned from the precision() function
// earlier. I.e. a fractional part of 0.01234 is
// represented as 1234 when the 'Precision' is 5.
// precision The number of digits to emit as returned by the
// function 'precision()' above
//
// This is given to allow to decide, whether a decimal point
// has to be generated at all.
//
// Note: If the trailing_zeros flag is not in effect additional
// comments apply. See the comment for the fraction_part()
// function below.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
{
return char_inserter<>::call(sink, '.'); // generate the dot by default
}
///////////////////////////////////////////////////////////////////////
// Generate the fractional part of the number.
//
// sink The output iterator to use for generation
// n The fractional part of the floating point number to
// convert. This number is scaled such, that it represents
// the number of units which correspond to the 'Precision'.
// I.e. a fractional part of 0.01234 is represented as 1234
// when the 'precision_' parameter is 5.
// precision_ The corrected number of digits to emit (see note
// below)
// precision The number of digits to emit as returned by the
// function 'precision()' above
//
// Note: If trailing_zeros() does not return true the 'precision_'
// parameter will have been corrected from the value the
// precision() function returned earlier (defining the maximal
// number of fractional digits) in the sense, that it takes into
// account trailing zeros. I.e. a floating point number 0.0123
// and a value of 5 returned from precision() will result in:
//
// trailing_zeros is not specified:
// n 123
// precision_ 4
//
// trailing_zeros is specified:
// n 1230
// precision_ 5
//
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool fraction_part (OutputIterator& sink, T n
, unsigned precision_, unsigned precision)
{
// allow for ADL to find the correct overload for floor and log10
using namespace std;
// The following is equivalent to:
// generate(sink, right_align(precision, '0')[ulong], n);
// but it's spelled out to avoid inter-modular dependencies.
typename remove_const<T>::type digits =
(traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
bool r = true;
for (/**/; r && digits < precision_; digits = digits + 1)
r = char_inserter<>::call(sink, '0');
if (precision && r)
r = int_inserter<10>::call(sink, n);
return r;
}
///////////////////////////////////////////////////////////////////////
// Generate the exponential part of the number (this is called only
// if the floatfield() function returned the 'scientific' flag).
//
// sink The output iterator to use for generation
// n The (signed) exponential part of the floating point
// number to convert.
//
// The Tag template parameter is either of the type unused_type or
// describes the character class and conversion to be applied to any
// output possibly influenced by either the lower[...] or upper[...]
// directives.
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool exponent (OutputIterator& sink, long n)
{
long abs_n = traits::get_absolute_value(n);
bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
sign_inserter::call(sink, traits::test_zero(n)
, traits::test_negative(n), false);
// the C99 Standard requires at least two digits in the exponent
if (r && abs_n < 10)
r = char_inserter<CharEncoding, Tag>::call(sink, '0');
return r && int_inserter<10>::call(sink, abs_n);
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations for non-normal floats (NaN and
// Inf)
//
// sink The output iterator to use for generation
// n The (signed) floating point number to convert.
// force_sign Whether a sign has to be generated even for
// non-negative numbers
//
// The Tag template parameter is either of the type unused_type or
// describes the character class and conversion to be applied to any
// output possibly influenced by either the lower[...] or upper[...]
// directives.
//
// Note: These functions get called only if fpclassify() returned
// FP_INFINITY or FP_NAN.
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool nan (OutputIterator& sink, T n, bool force_sign)
{
return sign_inserter::call(
sink, false, traits::test_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "nan");
}
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool inf (OutputIterator& sink, T n, bool force_sign)
{
return sign_inserter::call(
sink, false, traits::test_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "inf");
}
};
}}}
#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
@@ -0,0 +1,576 @@
// Copyright (c) 2001-2011 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)
#if !defined(BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM)
#define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
namespace boost { namespace spirit
{
namespace tag
{
template <typename T, unsigned Radix>
struct uint_generator
{
BOOST_SPIRIT_IS_TAG()
};
}
namespace karma
{
///////////////////////////////////////////////////////////////////////
// This one is the class that the user can instantiate directly in
// order to create a customized int generator
template <typename T = unsigned int, unsigned Radix = 10>
struct uint_generator
: spirit::terminal<tag::uint_generator<T, Radix> >
{};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::ushort_> // enables ushort_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::uint_> // enables uint_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::ulong_> // enables ulong_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::bin> // enables bin
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::oct> // enables oct
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::hex> // enables hex
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, tag::ulong_long> // enables ulong_long
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <> // enables lit(unsigned short(0))
struct use_terminal<karma::domain, unsigned short>
: mpl::true_ {};
#endif
template <> // enables lit(0U)
struct use_terminal<karma::domain, unsigned int>
: mpl::true_ {};
template <> // enables lit(0UL)
struct use_terminal<karma::domain, unsigned long>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables lit(0ULL)
struct use_terminal<karma::domain, boost::ulong_long_type>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables ushort_(...)
, terminal_ex<tag::ushort_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables uint_(...)
, terminal_ex<tag::uint_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables ulong_(...)
, terminal_ex<tag::ulong_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables bin(...)
, terminal_ex<tag::bin, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables oct(...)
, terminal_ex<tag::oct, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables hex(...)
, terminal_ex<tag::hex, fusion::vector1<A0> >
> : mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <typename A0>
struct use_terminal<karma::domain // enables ulong_long(...)
, terminal_ex<tag::ulong_long, fusion::vector1<A0> >
> : mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <> // enables *lazy* ushort_(...)
struct use_lazy_terminal<karma::domain, tag::ushort_, 1>
: mpl::true_ {};
template <> // enables *lazy* uint_(...)
struct use_lazy_terminal<karma::domain, tag::uint_, 1>
: mpl::true_ {};
template <> // enables *lazy* ulong_(...)
struct use_lazy_terminal<karma::domain, tag::ulong_, 1>
: mpl::true_ {};
template <> // enables *lazy* bin(...)
struct use_lazy_terminal<karma::domain, tag::bin, 1>
: mpl::true_ {};
template <> // enables *lazy* oct(...)
struct use_lazy_terminal<karma::domain, tag::oct, 1>
: mpl::true_ {};
template <> // enables *lazy* hex(...)
struct use_lazy_terminal<karma::domain, tag::hex, 1>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables *lazy* ulong_long(...)
struct use_lazy_terminal<karma::domain, tag::ulong_long, 1>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
// enables any custom uint_generator
template <typename T, unsigned Radix>
struct use_terminal<karma::domain, tag::uint_generator<T, Radix> >
: mpl::true_ {};
// enables any custom uint_generator(...)
template <typename T, unsigned Radix, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
> : mpl::true_ {};
// enables *lazy* custom uint_generator
template <typename T, unsigned Radix>
struct use_lazy_terminal<
karma::domain
, tag::uint_generator<T, Radix>
, 1 // arity
> : mpl::true_ {};
// enables lit(uint)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_uint<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::ushort_;
using spirit::uint_;
using spirit::ulong_;
#ifdef BOOST_HAS_LONG_LONG
using spirit::ulong_long;
#endif
using spirit::bin;
using spirit::oct;
using spirit::hex;
using spirit::lit; // lit(1U) is equivalent to 1U
#endif
using spirit::ushort_type;
using spirit::uint_type;
using spirit::ulong_type;
#ifdef BOOST_HAS_LONG_LONG
using spirit::ulong_long_type;
#endif
using spirit::bin_type;
using spirit::oct_type;
using spirit::hex_type;
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for unsigned int generators not having a
// direct initializer: uint_, ulong_ etc. These generators must be used in
// conjunction with an Attribute.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag, unsigned Radix>
struct any_uint_generator
: primitive_generator<any_uint_generator<T, CharEncoding, Tag, Radix> >
{
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix >= 2 && Radix <= 36, not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(
// the following is a workaround for STLPort, where the simpler
// `!std::numeric_limits<T>::is_signed` wouldn't compile
mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
signed_unsigned_mismatch, ());
// int has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr)
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return uint_inserter<Radix, CharEncoding, Tag>::
call(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
// this int has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, uint_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("unsigned-integer");
}
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for unsigned int generators having a direct
// initializer: uint_(10), ulong_(20) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool no_attribute>
struct literal_uint_generator
: primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
, no_attribute> >
{
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_uint_generator(typename add_const<T>::type n)
: n_(n) {}
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix >= 2 && Radix <= 36, not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(
// the following is a workaround for STLPort, where the simpler
// `!std::numeric_limits<T>::is_signed wouldn't` compile
mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
signed_unsigned_mismatch, ());
// A uint(1U) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
delimit_out(sink, d); // always do post-delimiting
}
// A uint(1U) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("unsigned-integer");
}
T n_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10>
struct make_uint
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::ushort_, Modifiers>
: detail::make_uint<unsigned short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::uint_, Modifiers>
: detail::make_uint<unsigned int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::ulong_, Modifiers>
: detail::make_uint<unsigned long, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::bin, Modifiers>
: detail::make_uint<unsigned, Modifiers, 2> {};
template <typename Modifiers>
struct make_primitive<tag::oct, Modifiers>
: detail::make_uint<unsigned, Modifiers, 8> {};
template <typename Modifiers>
struct make_primitive<tag::hex, Modifiers>
: detail::make_uint<unsigned, Modifiers, 16> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<tag::ulong_long, Modifiers>
: detail::make_uint<boost::ulong_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, typename Modifiers>
struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
: detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10>
struct make_uint_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ushort_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned short, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::uint_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned int, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ulong_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned long, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::bin, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 2> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::oct, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 8> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::hex, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 16> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ulong_long, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<boost::ulong_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
, Modifiers>
: detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
{};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_uint_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <typename Modifiers>
struct make_primitive<unsigned short, Modifiers>
: detail::basic_uint_literal<unsigned short, Modifiers> {};
#endif
template <typename Modifiers>
struct make_primitive<unsigned int, Modifiers>
: detail::basic_uint_literal<unsigned int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<unsigned long, Modifiers>
: detail::basic_uint_literal<unsigned long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<boost::ulong_long_type, Modifiers>
: detail::basic_uint_literal<boost::ulong_long_type, Modifiers> {};
#endif
// lit(uint)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_uint<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif