stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -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
|
||||
+117
@@ -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
|
||||
+67
@@ -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
|
||||
|
||||
+774
@@ -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
|
||||
|
||||
+187
@@ -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)
|
||||
+334
@@ -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
|
||||
Reference in New Issue
Block a user