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

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,15 @@
// 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_ACTION_MAR_04_2007_0912AM)
#define BOOST_SPIRIT_KARMA_ACTION_MAR_04_2007_0912AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/action/action.hpp>
#endif
@@ -0,0 +1,137 @@
// 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_ACTION_MAR_07_2007_0851AM)
#define BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/action_dispatch.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
template <typename Subject, typename Action>
struct action : unary_generator<action<Subject, Action> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<Subject, Context, Iterator>
{};
action(Subject const& subject, Action f)
: subject(subject), f(f) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr_) const
{
typedef typename attribute<Context, unused_type>::type attr_type;
typedef traits::make_attribute<attr_type, Attribute> make_attribute;
// create a attribute if none is supplied
// this creates a _copy_ of the attribute because the semantic
// action will likely change parts of this
typedef traits::transform_attribute<
typename make_attribute::type, attr_type, domain> transform;
typename transform::type attr =
traits::pre_transform<domain, attr_type>(make_attribute::call(attr_));
// call the function, passing the attribute, the context and a bool
// flag that the client can set to false to fail generating.
return traits::action_dispatch<Subject>()(f, attr, ctx) &&
subject.generate(sink, ctx, d, attr);
}
template <typename Context>
info what(Context& context) const
{
// the action is transparent (does not add any info)
return subject.what(context);
}
subject_type subject;
Action f;
};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Karma action meta-compiler
template <>
struct make_component<karma::domain, tag::action>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
remove_const<typename Elements::car_type>::type
subject_type;
typedef typename
remove_const<typename Elements::cdr_type::car_type>::type
action_type;
typedef karma::action<subject_type, action_type> type;
};
template <typename Elements>
typename result<make_component(Elements, unused_type)>::type
operator()(Elements const& elements, unused_type) const
{
typename result<make_component(Elements, unused_type)>::type
result(elements.car, elements.cdr.car);
return result;
}
};
}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Action>
struct has_semantic_action<karma::action<Subject, Action> >
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Action, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::action<Subject, Action>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,16 @@
// 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_AUTO_NOV_29_2009_0324PM)
#define BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0324PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/auto/auto.hpp>
#include <boost/spirit/home/karma/detail/generate_auto.hpp>
#endif
@@ -0,0 +1,188 @@
// 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_AUTO_NOV_29_2009_0339PM)
#define BOOST_SPIRIT_KARMA_AUTO_NOV_29_2009_0339PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/spirit/home/support/detail/hold_any.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/auto/create_generator.hpp>
#include <boost/mpl/bool.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::auto_> // enables auto_
: mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables auto_(...)
, terminal_ex<tag::auto_, fusion::vector1<A0> >
> : mpl::true_ {};
template <> // enables auto_(f)
struct use_lazy_terminal<
karma::domain, tag::auto_, 1 /*arity*/
> : mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::auto_;
#endif
using spirit::auto_type;
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct auto_generator
: generator<auto_generator<Modifiers> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
template <typename Context, typename Unused>
struct attribute
{
typedef spirit::basic_hold_any<char> type;
};
auto_generator(Modifiers const& modifiers)
: modifiers_(modifiers) {}
// auto_generator 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
{
return compile<karma::domain>(create_generator<Attribute>(), modifiers_)
.generate(sink, context, d, attr);
}
// this auto_generator has no attribute attached, it needs to have been
// initialized from a value/variable
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 auto_ 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, auto_not_usable_without_attribute, ());
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("auto_");
}
Modifiers modifiers_;
};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Modifiers>
struct lit_auto_generator
: generator<lit_auto_generator<T, Modifiers> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
lit_auto_generator(typename add_reference<T>::type t, Modifiers const& modifiers)
: t_(t)
, generator_(compile<karma::domain>(create_generator<T>(), modifiers))
{}
// auto_generator has an attached attribute
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const&) const
{
return generator_.generate(sink, context, d, t_);
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("auto_");
}
typedef typename spirit::result_of::create_generator<T>::type
generator_type;
typedef typename spirit::result_of::compile<
karma::domain, generator_type, Modifiers>::type generator_impl_type;
T t_;
generator_impl_type generator_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
lit_auto_generator& operator= (lit_auto_generator const&);
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// auto_
template <typename Modifiers>
struct make_primitive<tag::auto_, Modifiers>
{
typedef auto_generator<Modifiers> result_type;
result_type operator()(unused_type, Modifiers const& modifiers) const
{
return result_type(modifiers);
}
};
// auto_(...)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::auto_, fusion::vector1<A0> >, Modifiers>
{
typedef typename add_const<A0>::type const_attribute;
typedef lit_auto_generator<const_attribute, Modifiers> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Modifiers const& modifiers) const
{
return result_type(fusion::at_c<0>(term.args), modifiers);
}
};
}}}
#endif
@@ -0,0 +1,46 @@
// 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_CREATE_NOV_21_2009_0340PM)
#define BOOST_SPIRIT_KARMA_CREATE_NOV_21_2009_0340PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/auto/meta_create.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct create_generator
: spirit::traits::meta_create<karma::domain, T> {};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
// Main API function for generator creation from data type
template <typename T>
typename result_of::create_generator<T>::type
create_generator()
{
return spirit::traits::meta_create<karma::domain, T>::call();
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
// Meta function returning true if create_generator does return a valid
// generator for the given type T.
template <typename T>
struct create_generator_exists
: meta_create_exists<karma::domain, T> {};
}}}
#endif
@@ -0,0 +1,339 @@
// 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_META_CREATE_NOV_21_2009_0425PM)
#define BOOST_SPIRIT_KARMA_META_CREATE_NOV_21_2009_0425PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/auto/meta_create.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant.hpp>
#include <boost/optional.hpp>
#include <boost/config.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/type_traits/is_same.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// compatible STL containers
template <typename Container>
struct meta_create_container
{
typedef make_unary_proto_expr<
typename Container::value_type
, proto::tag::dereference, karma::domain
> make_proto_expr;
typedef typename make_proto_expr::type type;
static type call()
{
return make_proto_expr::call();
}
};
///////////////////////////////////////////////////////////////////////////
// String types
template <typename String>
struct meta_create_string
{
typedef spirit::standard::string_type type;
static type const call() { return type(); }
};
template <>
struct meta_create_string<wchar_t*>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <>
struct meta_create_string<wchar_t const*>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <int N>
struct meta_create_string<wchar_t[N]>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <int N>
struct meta_create_string<wchar_t const[N]>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <int N>
struct meta_create_string<wchar_t(&)[N]>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <int N>
struct meta_create_string<wchar_t const(&)[N]>
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
template <typename Traits, typename Allocator>
struct meta_create_string<std::basic_string<wchar_t, Traits, Allocator> >
{
typedef spirit::standard_wide::string_type type;
static type const call() { return type(); }
};
///////////////////////////////////////////////////////////////////////////
// Fusion sequences
template <typename Sequence>
struct meta_create_sequence
{
// create a mpl sequence from the given fusion sequence
typedef typename mpl::fold<
typename fusion::result_of::as_vector<Sequence>::type
, mpl::vector<>, mpl::push_back<mpl::_, mpl::_>
>::type sequence_type;
typedef make_nary_proto_expr<
sequence_type, proto::tag::shift_left, karma::domain
> make_proto_expr;
typedef typename make_proto_expr::type type;
static type call()
{
return make_proto_expr::call();
}
};
///////////////////////////////////////////////////////////////////////////
// the default is to use the standard streaming operator unless it's a
// STL container or a fusion sequence
// The default implementation will be chosen if no predefined mapping of
// the data type T to a Karma component is defined.
struct no_auto_mapping_exists {};
template <typename T, typename Enable = void>
struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {};
template <typename T>
struct meta_create_impl<T
, typename enable_if<
mpl::and_<
traits::is_container<T>
, mpl::not_<traits::is_string<T> >
, mpl::not_<fusion::traits::is_sequence<T> >
> >::type>
: meta_create_container<T> {};
template <typename T>
struct meta_create_impl<T
, typename enable_if<traits::is_string<T> >::type>
: meta_create_string<T> {};
template <typename T>
struct meta_create_impl<T, typename enable_if<
spirit::detail::is_fusion_sequence_but_not_proto_expr<T>
>::type>
: meta_create_sequence<T> {};
template <typename T, typename Enable = void>
struct meta_create : meta_create_impl<T> {};
///////////////////////////////////////////////////////////////////////////
// optional
template <typename T>
struct meta_create<boost::optional<T> >
{
typedef make_unary_proto_expr<
T, proto::tag::negate, karma::domain
> make_proto_expr;
typedef typename make_proto_expr::type type;
static type call()
{
return make_proto_expr::call();
}
};
///////////////////////////////////////////////////////////////////////////
// alternatives
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
typedef make_nary_proto_expr<
typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
, proto::tag::bitwise_or, karma::domain
> make_proto_expr;
typedef typename make_proto_expr::type type;
static type call()
{
return make_proto_expr::call();
}
};
///////////////////////////////////////////////////////////////////////////
// predefined specializations for primitive components
// character generator
template <>
struct meta_create<char>
{
typedef spirit::standard::char_type type;
static type const call() { return type(); }
};
template <>
struct meta_create<signed char>
{
typedef spirit::standard::char_type type;
static type const call() { return type(); }
};
template <>
struct meta_create<wchar_t>
{
typedef spirit::standard_wide::char_type type;
static type const call() { return type(); }
};
template <>
struct meta_create<unsigned char>
{
typedef spirit::standard::char_type type;
static type const call() { return type(); }
};
// boolean generator
template <>
struct meta_create<bool>
{
typedef spirit::bool_type type;
static type call() { return type(); }
};
// integral generators
template <>
struct meta_create<int>
{
typedef spirit::int_type type;
static type call() { return type(); }
};
template <>
struct meta_create<short>
{
typedef spirit::short_type type;
static type call() { return type(); }
};
template <>
struct meta_create<long>
{
typedef spirit::long_type type;
static type call() { return type(); }
};
template <>
struct meta_create<unsigned int>
{
typedef spirit::uint_type type;
static type call() { return type(); }
};
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <>
struct meta_create<unsigned short>
{
typedef spirit::ushort_type type;
static type call() { return type(); }
};
#endif
template <>
struct meta_create<unsigned long>
{
typedef spirit::ulong_type type;
static type call() { return type(); }
};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct meta_create<boost::long_long_type>
{
typedef spirit::long_long_type type;
static type call() { return type(); }
};
template <>
struct meta_create<boost::ulong_long_type>
{
typedef spirit::ulong_long_type type;
static type call() { return type(); }
};
#endif
// floating point generators
template <>
struct meta_create<float>
{
typedef spirit::float_type type;
static type call() { return type(); }
};
template <>
struct meta_create<double>
{
typedef spirit::double_type type;
static type call() { return type(); }
};
template <>
struct meta_create<long double>
{
typedef spirit::long_double_type type;
static type call() { return type(); }
};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// main customization point for create_generator
template <typename T, typename Enable = void>
struct create_generator : karma::meta_create<T> {};
///////////////////////////////////////////////////////////////////////////
// dispatch this to the karma related specializations
template <typename T>
struct meta_create<karma::domain, T>
: create_generator<typename spirit::detail::remove_const_ref<T>::type> {};
///////////////////////////////////////////////////////////////////////////
// Check whether a valid mapping exits for the given data type to a Karma
// component
template <typename T>
struct meta_create_exists<karma::domain, T>
: mpl::not_<is_same<
karma::no_auto_mapping_exists
, typename meta_create<karma::domain, T>::type
> > {};
}}}
#endif
@@ -0,0 +1,18 @@
// 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_AUXILIARY_MAR_26_2007_1225PM)
#define BOOST_SPIRIT_KARMA_AUXILIARY_MAR_26_2007_1225PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/auxiliary/eps.hpp>
#include <boost/spirit/home/karma/auxiliary/eol.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/auxiliary/attr_cast.hpp>
#endif
@@ -0,0 +1,120 @@
// 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(SPIRIT_KARMA_ATTR_CAST_SEP_26_2009_0348PM)
#define SPIRIT_KARMA_ATTR_CAST_SEP_26_2009_0348PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/auxiliary/attr_cast.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// enables attr_cast<>() pseudo generator
template <typename Expr, typename Exposed, typename Transformed>
struct use_terminal<karma::domain
, tag::stateful_tag<Expr, tag::attr_cast, Exposed, Transformed> >
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::attr_cast;
#endif
///////////////////////////////////////////////////////////////////////////
// attr_cast_generator consumes the attribute of subject generator without
// generating anything
///////////////////////////////////////////////////////////////////////////
template <typename Exposed, typename Transformed, typename Subject>
struct attr_cast_generator
: unary_generator<attr_cast_generator<Exposed, Transformed, Subject> >
{
typedef typename result_of::compile<karma::domain, Subject>::type
subject_type;
typedef mpl::int_<subject_type::properties::value> properties;
typedef typename mpl::eval_if<
traits::not_is_unused<Transformed>
, mpl::identity<Transformed>
, traits::attribute_of<subject_type> >::type
transformed_attribute_type;
attr_cast_generator(Subject const& subject)
: subject(subject)
{
// If you got an error_invalid_expression error message here,
// then the expression (Subject) is not a valid spirit karma
// expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Subject);
}
// If Exposed is given, we use the given type, otherwise all we can do
// is to guess, so we expose our inner type as an attribute and
// deal with the passed attribute inside the parse function.
template <typename Context, typename Unused>
struct attribute
: mpl::if_<traits::not_is_unused<Exposed>, Exposed
, transformed_attribute_type>
{};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
typedef traits::transform_attribute<
Attribute const, transformed_attribute_type, domain>
transform;
return compile<karma::domain>(subject).generate(
sink, ctx, d, transform::pre(attr));
}
template <typename Context>
info what(Context& context) const
{
return info("attr_cast"
, compile<karma::domain>(subject).what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generator: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Exposed, typename Transformed
, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Expr, tag::attr_cast, Exposed, Transformed>, Modifiers>
{
typedef attr_cast_generator<Exposed, Transformed, Expr> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<
Expr, tag::attr_cast, Exposed, Transformed> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term));
}
};
}}}
#endif
@@ -0,0 +1,81 @@
// 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_EOL_JUL_08_2008_1014AM)
#define BOOST_SPIRIT_KARMA_EOL_JUL_08_2008_1014AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::eol> // enables eol
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::eol;
#endif
using boost::spirit::eol_type;
struct eol_generator : primitive_generator<eol_generator>
{
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const& /*attr*/)
{
return detail::generate_to(sink, '\n') &&
karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
info what(Context const& /*context*/) const
{
return info("eol");
}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::eol, Modifiers>
{
typedef eol_generator result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}}}
#endif
@@ -0,0 +1,137 @@
// 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_EPS_APRIL_21_2007_0246PM)
#define BOOST_SPIRIT_KARMA_EPS_APRIL_21_2007_0246PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/fusion/include/at.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables eps
template <>
struct use_terminal<karma::domain, tag::eps>
: mpl::true_ {};
// enables eps(bool-condition)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::eps, fusion::vector1<A0> > >
: is_convertible<A0, bool> {};
// enables lazy eps(f)
template <>
struct use_lazy_terminal<karma::domain, tag::eps, 1>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::eps;
#endif
using boost::spirit::eps_type;
struct eps_generator : primitive_generator<eps_generator>
{
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const& /*attr*/)
{
return karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
info what(Context const& /*context*/) const
{
return info("eps");
}
};
struct semantic_predicate : primitive_generator<semantic_predicate>
{
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
semantic_predicate(bool predicate)
: predicate_(predicate)
{}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const& /*attr*/) const
{
// only do post-delimiting when predicate is true
return predicate_ && karma::delimit_out(sink, d);
}
template <typename Context>
info what(Context const& /*context*/) const
{
return info("semantic-predicate");
}
bool predicate_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::eps, Modifiers>
{
typedef eps_generator result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::eps, fusion::vector1<A0> >
, Modifiers>
{
typedef semantic_predicate 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,267 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM)
#define BOOST_SPIRIT_KARMA_LAZY_MARCH_27_2007_1231PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/lazy.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/mpl/not.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <typename Eval>
struct use_terminal<karma::domain, phoenix::actor<Eval> > // enables phoenix actors
: mpl::true_ {};
// forward declaration
template <typename Terminal, typename Actor, int Arity>
struct lazy_terminal;
}}
namespace boost { namespace spirit { namespace karma
{
using spirit::lazy;
typedef modify<karma::domain> karma_modify;
namespace detail
{
template <typename Generator, typename OutputIterator, typename Context
, typename Delimiter, typename Attribute>
bool lazy_generate_impl(Generator const& g, OutputIterator& sink
, Context& context, Delimiter const& delim
, Attribute const& attr, mpl::false_)
{
return g.generate(sink, context, delim, attr);
}
template <typename Generator, typename OutputIterator, typename Context
, typename Delimiter, typename Attribute>
bool lazy_generate_impl(Generator const& g, OutputIterator& sink
, Context& context, Delimiter const& delim
, Attribute const& attr, mpl::true_)
{
// If DeducedAuto is false (semantic actions is present), the
// component's attribute is unused.
return g.generate(sink, context, delim, unused);
}
template <typename Generator, typename OutputIterator, typename Context
, typename Delimiter, typename Attribute>
bool lazy_generate_impl_main(Generator const& g, OutputIterator& sink
, Context& context, Delimiter const& delim, Attribute const& attr)
{
// If DeducedAuto is true (no semantic action), we pass the parser's
// attribute on to the component.
typedef typename traits::has_semantic_action<Generator>::type auto_rule;
return lazy_generate_impl(g, sink, context, delim, attr, auto_rule());
}
}
template <typename Function, typename Modifiers>
struct lazy_generator : generator<lazy_generator<Function, Modifiers> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
template <typename Context, typename Iterator>
struct attribute
{
typedef typename
boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
modifier;
typedef typename
remove_reference<
typename boost::result_of<Function(unused_type, Context)>::type
>::type
expr_type;
// If you got an error_invalid_expression error message here,
// then the expression (expr_type) is not a valid spirit karma
// expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
typedef typename
result_of::compile<karma::domain, expr_type, modifier>::type
generator_type;
typedef typename
traits::attribute_of<generator_type, Context, Iterator>::type
type;
};
lazy_generator(Function const& func, Modifiers const& modifiers)
: func(func), modifiers(modifiers) {}
template <
typename OutputIterator, typename Context,
typename Delimiter, typename Attribute
>
bool generate(OutputIterator& sink, Context& context,
Delimiter const& d, Attribute const& attr) const
{
return detail::lazy_generate_impl_main(
compile<karma::domain>(func(unused, context)
, karma_modify()(tag::lazy_eval(), modifiers))
, sink, context, d, attr);
}
template <typename Context>
info what(Context& context) const
{
return info("lazy"
, compile<karma::domain>(func(unused, context)
, karma_modify()(tag::lazy_eval(), modifiers))
.what(context)
);
}
Function func;
Modifiers modifiers;
private:
// silence MSVC warning C4512: assignment operator could not be generated
lazy_generator& operator= (lazy_generator const&);
};
///////////////////////////////////////////////////////////////////////////
template <typename Function, typename Subject, typename Modifiers>
struct lazy_directive
: unary_generator<lazy_directive<Function, Subject, Modifiers> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
typedef Subject subject_type;
template <typename Context, typename Iterator>
struct attribute
{
typedef typename
boost::result_of<karma_modify(tag::lazy_eval, Modifiers)>::type
modifier;
typedef typename
remove_reference<
typename boost::result_of<Function(unused_type, Context)>::type
>::type
directive_expr_type;
typedef typename
proto::result_of::make_expr<
proto::tag::subscript
, directive_expr_type
, Subject
>::type
expr_type;
// If you got an error_invalid_expression error message here,
// then the expression (expr_type) is not a valid spirit karma
// expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, expr_type);
typedef typename
result_of::compile<karma::domain, expr_type, modifier>::type
generator_type;
typedef typename
traits::attribute_of<generator_type, Context, Iterator>::type
type;
};
lazy_directive(Function const& function, Subject const& subject
, Modifiers const& modifiers)
: function(function), subject(subject), modifiers(modifiers) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::lazy_generate_impl_main(compile<karma::domain>(
proto::make_expr<proto::tag::subscript>(
function(unused, ctx), subject)
, karma_modify()(tag::lazy_eval(), modifiers))
, sink, ctx, d, attr);
}
template <typename Context>
info what(Context& ctx) const
{
return info("lazy-directive"
, compile<karma::domain>(
proto::make_expr<proto::tag::subscript>(
function(unused, ctx), subject)
, karma_modify()(tag::lazy_eval(), modifiers))
.what(ctx)
);
}
Function function;
Subject subject;
Modifiers modifiers;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Eval, typename Modifiers>
struct make_primitive<phoenix::actor<Eval>, Modifiers>
{
typedef lazy_generator<phoenix::actor<Eval>, Modifiers> result_type;
result_type operator()(phoenix::actor<Eval> const& f
, Modifiers const& modifiers) const
{
return result_type(f, modifiers);
}
};
template <typename Terminal, typename Actor, int Arity, typename Modifiers>
struct make_primitive<lazy_terminal<Terminal, Actor, Arity>, Modifiers>
{
typedef lazy_generator<Actor, Modifiers> result_type;
result_type operator()(
lazy_terminal<Terminal, Actor, Arity> const& lt
, Modifiers const& modifiers) const
{
return result_type(lt.actor, modifiers);
}
};
template <
typename Terminal, typename Actor, int Arity, typename Subject
, typename Modifiers>
struct make_directive<lazy_terminal<Terminal, Actor, Arity>
, Subject, Modifiers>
{
typedef lazy_directive<Actor, Subject, Modifiers> result_type;
result_type operator()(
lazy_terminal<Terminal, Actor, Arity> const& lt
, Subject const& subject, Modifiers const& modifiers) const
{
return result_type(lt.actor, subject, modifiers);
}
};
}}}
#endif
@@ -0,0 +1,16 @@
// 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_BINARY_MAY_04_2007_0859AM)
#define BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0859AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/binary/binary.hpp>
#include <boost/spirit/home/karma/binary/padding.hpp>
#endif
@@ -0,0 +1,438 @@
// 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_BINARY_MAY_04_2007_0904AM)
#define BOOST_SPIRIT_KARMA_BINARY_MAY_04_2007_0904AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/detail/endian.hpp>
#include <boost/spirit/home/karma/domain.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/generate_to.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/config.hpp>
///////////////////////////////////////////////////////////////////////////////
#define BOOST_SPIRIT_ENABLE_BINARY(name) \
template <> \
struct use_terminal<karma::domain, tag::name> \
: mpl::true_ {}; \
\
template <typename A0> \
struct use_terminal<karma::domain \
, terminal_ex<tag::name, fusion::vector1<A0> > > \
: mpl::or_<is_integral<A0>, is_enum<A0> > {}; \
\
template <> \
struct use_lazy_terminal<karma::domain, tag::name, 1> : mpl::true_ {}; \
\
/***/
#define BOOST_SPIRIT_ENABLE_BINARY_IEEE754(name) \
template<> \
struct use_terminal<karma::domain, tag::name>: mpl::true_ {}; \
\
template<typename A0> \
struct use_terminal<karma::domain, terminal_ex<tag::name, \
fusion::vector1<A0> > >: is_floating_point<A0> {}; \
\
template<> \
struct use_lazy_terminal<karma::domain, tag::name, 1> : mpl::true_ {}; \
\
/***/
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
BOOST_SPIRIT_ENABLE_BINARY(byte_) // enables byte_
BOOST_SPIRIT_ENABLE_BINARY(word) // enables word
BOOST_SPIRIT_ENABLE_BINARY(big_word) // enables big_word
BOOST_SPIRIT_ENABLE_BINARY(little_word) // enables little_word
BOOST_SPIRIT_ENABLE_BINARY(dword) // enables dword
BOOST_SPIRIT_ENABLE_BINARY(big_dword) // enables big_dword
BOOST_SPIRIT_ENABLE_BINARY(little_dword) // enables little_dword
#ifdef BOOST_HAS_LONG_LONG
BOOST_SPIRIT_ENABLE_BINARY(qword) // enables qword
BOOST_SPIRIT_ENABLE_BINARY(big_qword) // enables big_qword
BOOST_SPIRIT_ENABLE_BINARY(little_qword) // enables little_qword
#endif
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(bin_float)
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(big_bin_float)
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(little_bin_float)
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(bin_double)
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(big_bin_double)
BOOST_SPIRIT_ENABLE_BINARY_IEEE754(little_bin_double)
}}
#undef BOOST_SPIRIT_ENABLE_BINARY
#undef BOOST_SPIRIT_ENABLE_BINARY_IEEE754
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::byte_;
using boost::spirit::word;
using boost::spirit::big_word;
using boost::spirit::little_word;
using boost::spirit::dword;
using boost::spirit::big_dword;
using boost::spirit::little_dword;
#ifdef BOOST_HAS_LONG_LONG
using boost::spirit::qword;
using boost::spirit::big_qword;
using boost::spirit::little_qword;
#endif
using boost::spirit::bin_float;
using boost::spirit::big_bin_float;
using boost::spirit::little_bin_float;
using boost::spirit::bin_double;
using boost::spirit::big_bin_double;
using boost::spirit::little_bin_double;
#endif
using boost::spirit::byte_type;
using boost::spirit::word_type;
using boost::spirit::big_word_type;
using boost::spirit::little_word_type;
using boost::spirit::dword_type;
using boost::spirit::big_dword_type;
using boost::spirit::little_dword_type;
#ifdef BOOST_HAS_LONG_LONG
using boost::spirit::qword_type;
using boost::spirit::big_qword_type;
using boost::spirit::little_qword_type;
#endif
using boost::spirit::bin_float_type;
using boost::spirit::big_bin_float_type;
using boost::spirit::little_bin_float_type;
using boost::spirit::bin_double_type;
using boost::spirit::big_bin_double_type;
using boost::spirit::little_bin_double_type;
namespace detail
{
template <int bits>
struct integer
{
#ifdef BOOST_HAS_LONG_LONG
BOOST_SPIRIT_ASSERT_MSG(
bits == 8 || bits == 16 || bits == 32 || bits == 64,
not_supported_binary_size, ());
#else
BOOST_SPIRIT_ASSERT_MSG(
bits == 8 || bits == 16 || bits == 32,
not_supported_binary_size, ());
#endif
};
template <>
struct integer<8>
{
typedef uint_least8_t type;
};
template <>
struct integer<16>
{
typedef uint_least16_t type;
};
template <>
struct integer<32>
{
typedef uint_least32_t type;
};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct integer<64>
{
typedef uint_least64_t type;
};
#endif
template <int bits>
struct floating_point
{
BOOST_SPIRIT_ASSERT_MSG(
bits == 32 || bits == 64,
not_supported_binary_size, ());
};
template <>
struct floating_point<32>
{
typedef float type;
};
template <>
struct floating_point<64>
{
typedef double type;
};
///////////////////////////////////////////////////////////////////////
template <BOOST_SCOPED_ENUM(boost::endian::endianness) bits>
struct what;
template <>
struct what<boost::endian::endianness::native>
{
static info is()
{
return info("native-endian binary");
}
};
template <>
struct what<boost::endian::endianness::little>
{
static info is()
{
return info("little-endian binary");
}
};
template <>
struct what<boost::endian::endianness::big>
{
static info is()
{
return info("big-endian binary");
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename T, BOOST_SCOPED_ENUM(boost::endian::endianness) endian, int bits>
struct any_binary_generator
: primitive_generator<any_binary_generator<T, endian, bits> >
{
template <typename Context, typename Unused = unused_type>
struct attribute: T {};
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;
// Even if the endian types are not pod's (at least not in the
// definition of C++03) it seems to be safe to assume they are.
// This allows us to treat them as a sequence of consecutive bytes.
boost::endian::endian<endian, typename T::type, bits> p;
#if defined(BOOST_MSVC)
// warning C4244: 'argument' : conversion from 'const int' to 'foo', possible loss of data
#pragma warning(push)
#pragma warning(disable: 4244)
#endif
typedef typename T::type attribute_type;
p = traits::extract_from<attribute_type>(attr, context);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
unsigned char const* bytes =
reinterpret_cast<unsigned char const*>(&p);
for (unsigned int i = 0; i < sizeof(p); ++i)
{
if (!detail::generate_to(sink, *bytes++))
return false;
}
return karma::delimit_out(sink, d); // always do post-delimiting
}
// this any_byte_director has no parameter 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 binary 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,
binary_generator_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return karma::detail::what<endian>::is();
}
};
///////////////////////////////////////////////////////////////////////////
template <typename T, BOOST_SCOPED_ENUM(boost::endian::endianness) endian, int bits>
struct literal_binary_generator
: primitive_generator<literal_binary_generator<T, endian, bits> >
{
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
template <typename V>
literal_binary_generator(V const& v)
{
#if defined(BOOST_MSVC)
// warning C4244: 'argument' : conversion from 'const int' to 'foo', possible loss of data
#pragma warning(push)
#pragma warning(disable: 4244)
#endif
data_ = v;
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const&) const
{
// Even if the endian types are not pod's (at least not in the
// definition of C++03) it seems to be safe to assume they are
// (but in C++0x the endian types _are_ PODs).
// This allows us to treat them as a sequence of consecutive bytes.
unsigned char const* bytes =
reinterpret_cast<unsigned char const*>(&data_);
for (unsigned int i = 0; i < sizeof(data_type); ++i)
{
if (!detail::generate_to(sink, *bytes++))
return false;
}
return karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
static info what(Context const& /*context*/)
{
return karma::detail::what<endian>::is();
}
typedef boost::endian::endian<endian, typename T::type,
bits> data_type;
data_type data_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, BOOST_SCOPED_ENUM(boost::endian::endianness) endian
, int bits>
struct basic_binary
{
typedef any_binary_generator<T, endian, bits> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
template <typename Modifiers, typename T
, BOOST_SCOPED_ENUM(boost::endian::endianness) endian, int bits>
struct basic_binary_literal
{
typedef literal_binary_generator<T, endian, bits> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
#define BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(name, endiantype, bits) \
template <typename Modifiers> \
struct make_primitive<tag::name, Modifiers> \
: detail::basic_binary<detail::integer<bits>, \
boost::endian::endianness::endiantype, bits> {}; \
\
template <typename Modifiers, typename A0> \
struct make_primitive<terminal_ex<tag::name, fusion::vector1<A0> > \
, Modifiers> \
: detail::basic_binary_literal<Modifiers, detail::integer<bits> \
, boost::endian::endianness::endiantype, bits> {}; \
\
/***/
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(byte_, native, 8)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(word, native, 16)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_word, big, 16)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_word, little, 16)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(dword, native, 32)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_dword, big, 32)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_dword, little, 32)
#ifdef BOOST_HAS_LONG_LONG
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(qword, native, 64)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(big_qword, big, 64)
BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE(little_qword, little, 64)
#endif
#undef BOOST_SPIRIT_MAKE_BINARY_PRIMITIVE
#define BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(name, endiantype, bits) \
template <typename Modifiers> \
struct make_primitive<tag::name, Modifiers> \
: detail::basic_binary<detail::floating_point<bits>, \
boost::endian::endianness::endiantype, bits> {}; \
\
template <typename Modifiers, typename A0> \
struct make_primitive<terminal_ex<tag::name, fusion::vector1<A0> > \
, Modifiers> \
: detail::basic_binary_literal<Modifiers, detail::floating_point<bits> \
, boost::endian::endianness::endiantype, bits> {}; \
\
/***/
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(bin_float, native, 32)
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(big_bin_float, big, 32)
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(little_bin_float, little, 32)
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(bin_double, native, 64)
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(big_bin_double, big, 64)
BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE(little_bin_double, little, 64)
#undef BOOST_SPIRIT_MAKE_BINARY_IEEE754_PRIMITIVE
}}}
#endif
@@ -0,0 +1,115 @@
// 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_PADDING_MAY_06_2008_0436PM)
#define BOOST_SPIRIT_KARMA_PADDING_MAY_06_2008_0436PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/karma/domain.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/generate_to.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables pad(...)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::pad, fusion::vector1<A0> > >
: mpl::true_ {};
// enables lazy pad(...)
template <>
struct use_lazy_terminal<karma::domain, tag::pad, 1>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::pad;
#endif
using boost::spirit::pad_type;
struct binary_padding_generator
: primitive_generator<binary_padding_generator>
{
typedef mpl::int_<generator_properties::tracking> properties;
template <typename Context, typename Unused>
struct attribute
{
typedef unused_type type;
};
binary_padding_generator(int numpadbytes)
: numpadbytes_(numpadbytes)
{}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, Attribute const& /*attr*/) const
{
std::size_t count = sink.get_out_count() % numpadbytes_;
if (count)
count = numpadbytes_ - count;
bool result = true;
while (result && count-- != 0)
result = detail::generate_to(sink, '\0');
if (result)
result = karma::delimit_out(sink, d); // always do post-delimiting
return result;
}
template <typename Context>
static info what(Context const&)
{
return info("pad");
}
int numpadbytes_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::pad, fusion::vector1<A0> >
, Modifiers>
{
typedef binary_padding_generator 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,16 @@
// 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_CHAR_FEB_21_2007_0547PM)
#define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0547PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/char/char.hpp>
#include <boost/spirit/home/karma/char/char_class.hpp>
#endif
@@ -0,0 +1,547 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2010 Bryce Lelbach
//
// 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_CHAR_FEB_21_2007_0543PM)
#define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/char_set/basic_chset.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/char/char_generator.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/cons.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <string>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding>
struct use_terminal<karma::domain
, tag::char_code<tag::char_, CharEncoding> // enables char_
> : mpl::true_ {};
template <typename CharEncoding, typename A0>
struct use_terminal<karma::domain
, terminal_ex<
tag::char_code<tag::char_, CharEncoding> // enables char_('x'), char_("x")
, fusion::vector1<A0>
>
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> > // enables lit('x')
, typename enable_if<traits::is_char<A0> >::type>
: mpl::true_ {};
template <typename CharEncoding, typename A0, typename A1>
struct use_terminal<karma::domain
, terminal_ex<
tag::char_code<tag::char_, CharEncoding> // enables char_('a','z')
, fusion::vector2<A0, A1>
>
> : mpl::true_ {};
template <typename CharEncoding> // enables *lazy* char_('x'), char_("x")
struct use_lazy_terminal<
karma::domain
, tag::char_code<tag::char_, CharEncoding>
, 1 // arity
> : mpl::true_ {};
template <>
struct use_terminal<karma::domain, char> // enables 'x'
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, char[2]> // enables "x"
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, wchar_t> // enables L'x'
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, wchar_t[2]> // enables L"x"
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::lit; // lit('x') is equivalent to 'x'
#endif
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
//
// any_char
// generates a single character from the associated attribute
//
// Note: this generator has to have an associated attribute
//
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag>
struct any_char
: char_generator<any_char<CharEncoding, Tag>, CharEncoding, Tag>
{
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
template <typename Context, typename Unused>
struct attribute
{
typedef char_type type;
};
// any_char has an attached parameter
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context&) const
{
ch = CharParam(attr);
return true;
}
// any_char has no attribute attached, it needs to have been
// initialized from a direct literal
template <typename CharParam, typename Context>
bool test(unused_type, CharParam&, Context&) const
{
// It is not possible (doesn't make sense) to use char_ without
// providing any attribute, as the generator doesn't 'know' what
// character to output. The following assertion fires if this
// situation is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(CharParam, char_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("any-char");
}
};
///////////////////////////////////////////////////////////////////////////
//
// literal_char
// generates a single character given by a literal it was initialized
// from
//
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, bool no_attribute>
struct literal_char
: char_generator<literal_char<CharEncoding, Tag, no_attribute>
, CharEncoding, Tag>
{
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
literal_char(char_type ch)
: ch (spirit::char_class::convert<char_encoding>::to(Tag(), ch))
{}
template <typename Context, typename Unused>
struct attribute
: mpl::if_c<no_attribute, unused_type, char_type>
{};
// A char_('x') which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
// any_char has an attached parameter
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch_, Context&) const
{
// fail if attribute isn't matched my immediate literal
ch_ = attr;
return attr == ch;
}
// A char_('x') without any associated attribute just emits its
// immediate literal
template <typename CharParam, typename Context>
bool test(unused_type, CharParam& ch_, Context&) const
{
ch_ = ch;
return true;
}
template <typename Context>
info what(Context const& /*context*/) const
{
return info("literal-char", char_encoding::toucs4(ch));
}
char_type ch;
};
///////////////////////////////////////////////////////////////////////////
// char range generator
template <typename CharEncoding, typename Tag>
struct char_range
: char_generator<char_range<CharEncoding, Tag>, CharEncoding, Tag>
{
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
char_range(char_type from, char_type to)
: from(spirit::char_class::convert<char_encoding>::to(Tag(), from))
, to(spirit::char_class::convert<char_encoding>::to(Tag(), to))
{}
// A char_('a', 'z') which has an associated attribute emits it only if
// it matches the character range, otherwise it fails.
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context&) const
{
// fail if attribute doesn't belong to character range
ch = attr;
return (from <= char_type(attr)) && (char_type(attr) <= to);
}
// A char_('a', 'z') without any associated attribute fails compiling
template <typename CharParam, typename Context>
bool test(unused_type, CharParam&, Context&) const
{
// It is not possible (doesn't make sense) to use char_ 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(CharParam
, char_range_not_usable_without_attribute, ());
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
info result("char-range", char_encoding::toucs4(from));
boost::get<std::string>(result.value) += '-';
boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to));
return result;
}
char_type from, to;
};
///////////////////////////////////////////////////////////////////////////
// character set generator
template <typename CharEncoding, typename Tag, bool no_attribute>
struct char_set
: char_generator<char_set<CharEncoding, Tag, no_attribute>
, CharEncoding, Tag>
{
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
template <typename Context, typename Unused>
struct attribute
: mpl::if_c<no_attribute, unused_type, char_type>
{};
template <typename String>
char_set(String const& str)
{
typedef typename traits::char_type_of<String>::type in_type;
BOOST_SPIRIT_ASSERT_MSG((
(sizeof(char_type) == sizeof(in_type))
), cannot_convert_string, (String));
typedef spirit::char_class::convert<char_encoding> convert_type;
char_type const* definition =
(char_type const*)traits::get_c_string(str);
char_type ch = convert_type::to(Tag(), *definition++);
while (ch)
{
char_type next = convert_type::to(Tag(), *definition++);
if (next == '-')
{
next = convert_type::to(Tag(), *definition++);
if (next == 0)
{
chset.set(ch);
chset.set('-');
break;
}
chset.set(ch, next);
}
else
{
chset.set(ch);
}
ch = next;
}
}
// A char_("a-z") which has an associated attribute emits it only if
// it matches the character set, otherwise it fails.
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context&) const
{
// fail if attribute doesn't belong to character set
ch = attr;
return chset.test(char_type(attr));
}
// A char_("a-z") without any associated attribute fails compiling
template <typename CharParam, typename Context>
bool test(unused_type, CharParam&, Context&) const
{
// It is not possible (doesn't make sense) to use char_ 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(CharParam
, char_set_not_usable_without_attribute, ());
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("char-set");
}
support::detail::basic_chset<char_type> chset;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers, typename Encoding>
struct basic_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_char<
typename spirit::detail::get_encoding_with_case<
Modifiers, Encoding, lower || upper>::type
, typename get_casetag<Modifiers, lower || upper>::type
, true>
result_type;
template <typename Char>
result_type operator()(Char ch, unused_type) const
{
return result_type(ch);
}
template <typename Char>
result_type operator()(Char const* str, unused_type) const
{
return result_type(str[0]);
}
};
}
// literals: 'x', "x"
template <typename Modifiers>
struct make_primitive<char, Modifiers>
: detail::basic_literal<Modifiers, char_encoding::standard> {};
template <typename Modifiers>
struct make_primitive<char const(&)[2], Modifiers>
: detail::basic_literal<Modifiers, char_encoding::standard> {};
// literals: L'x', L"x"
template <typename Modifiers>
struct make_primitive<wchar_t, Modifiers>
: detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
template <typename Modifiers>
struct make_primitive<wchar_t const(&)[2], Modifiers>
: detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
// char_
template <typename CharEncoding, typename Modifiers>
struct make_primitive<tag::char_code<tag::char_, CharEncoding>, 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 any_char<
typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename CharEncoding, typename Modifiers, typename A0
, bool no_attribute>
struct make_char_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 typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, lower || upper>::type encoding;
typedef typename detail::get_casetag<
Modifiers, lower || upper>::type tag;
typedef typename mpl::if_<
traits::is_string<A0>
, char_set<encoding, tag, no_attribute>
, literal_char<encoding, tag, no_attribute>
>::type result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
// char_(...), lit(...)
template <typename CharEncoding, typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector1<A0> >
, Modifiers>
: detail::make_char_direct<CharEncoding, Modifiers, A0, false>
{};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_char<A0> >::type>
: detail::make_char_direct<
typename traits::char_encoding_from_char<
typename traits::char_type_of<A0>::type>::type
, Modifiers, A0, true>
{};
///////////////////////////////////////////////////////////////////////////
// char_("x")
template <typename CharEncoding, typename Modifiers, typename Char>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector1<Char(&)[2]> > // For single char strings
, 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_char<
typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, 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
{
return result_type(fusion::at_c<0>(term.args)[0]);
}
};
///////////////////////////////////////////////////////////////////////////
// char_('a', 'z')
template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector2<A0, A1>
>
, 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 char_range<
typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, 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
{
return result_type(fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args));
}
};
template <typename CharEncoding, typename Modifiers, typename Char>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings
>
, 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 char_range<
typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, 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
{
return result_type(fusion::at_c<0>(term.args)[0]
, fusion::at_c<1>(term.args)[0]);
}
};
}}} // namespace boost::spirit::karma
#endif
@@ -0,0 +1,226 @@
// 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_CHAR_CLASS_AUG_10_2009_0720AM)
#define BOOST_SPIRIT_KARMA_CHAR_CLASS_AUG_10_2009_0720AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/char/char_generator.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables alnum, alpha, graph, etc.
template <typename CharClass, typename CharEncoding>
struct use_terminal<karma::domain
, tag::char_code<CharClass, CharEncoding> >
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
// hoist the char classification namespaces into karma sub-namespaces of
// the same name
namespace ascii { using namespace boost::spirit::ascii; }
namespace iso8859_1 { using namespace boost::spirit::iso8859_1; }
namespace standard { using namespace boost::spirit::standard; }
namespace standard_wide { using namespace boost::spirit::standard_wide; }
#if defined(BOOST_SPIRIT_UNICODE)
namespace unicode { using namespace boost::spirit::unicode; }
#endif
// Import the standard namespace into the karma namespace. This allows
// for default handling of all character/string related operations if not
// prefixed with a character set namespace.
using namespace boost::spirit::standard;
// Import encoding
using spirit::encoding;
///////////////////////////////////////////////////////////////////////////
//
// char_class
// generates a single character if it matches the given character
// class
//
///////////////////////////////////////////////////////////////////////////
template <typename Tag, typename CharEncoding, typename CharClass>
struct char_class
: char_generator<
char_class<Tag, CharEncoding, CharClass>
, CharEncoding, CharClass>
{
typedef typename Tag::char_encoding char_encoding;
typedef typename char_encoding::char_type char_type;
typedef typename Tag::char_class classification;
template <typename Context, typename Unused>
struct attribute
{
typedef char_type type;
};
// char_class needs an attached attribute
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context&) const
{
ch = attr;
using spirit::char_class::classify;
return classify<char_encoding>::is(classification(), attr);
}
// char_class shouldn't be used without any associated attribute
template <typename CharParam, typename Context>
bool test(unused_type, CharParam&, Context&) const
{
// It is not possible (doesn't make sense) to use char_ 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(CharParam
, char_class_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
typedef spirit::char_class::what<char_encoding> what_;
return info(what_::is(classification()));
}
};
///////////////////////////////////////////////////////////////////////////
//
// space
// generates a single character from the associated parameter
//
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding>
struct any_space
: char_generator<any_space<CharEncoding>, CharEncoding, tag::space>
{
typedef typename CharEncoding::char_type char_type;
typedef CharEncoding char_encoding;
template <typename Context, typename Unused>
struct attribute
{
typedef char_type type;
};
// any_space has an attached parameter
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context&) const
{
ch = CharParam(attr);
using spirit::char_class::classify;
return classify<char_encoding>::is(tag::space(), attr);
}
// any_space has no attribute attached, use single space character
template <typename CharParam, typename Context>
bool test(unused_type, CharParam& ch, Context&) const
{
ch = ' ';
return true;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("space");
}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Tag, bool lower = false, bool upper = false>
struct make_char_class : mpl::identity<Tag> {};
template <>
struct make_char_class<tag::alpha, true, false>
: mpl::identity<tag::lower> {};
template <>
struct make_char_class<tag::alpha, false, true>
: mpl::identity<tag::upper> {};
template <>
struct make_char_class<tag::alnum, true, false>
: mpl::identity<tag::lowernum> {};
template <>
struct make_char_class<tag::alnum, false, true>
: mpl::identity<tag::uppernum> {};
}
// enables alnum, alpha, graph, etc.
template <typename CharClass, typename CharEncoding, typename Modifiers>
struct make_primitive<tag::char_code<CharClass, CharEncoding>, 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 tag::char_code<
typename detail::make_char_class<CharClass, lower, upper>::type
, CharEncoding>
tag_type;
typedef char_class<
tag_type
, typename spirit::detail::get_encoding_with_case<
Modifiers, CharEncoding, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
// space is special
template <typename CharEncoding, typename Modifiers>
struct make_primitive<tag::char_code<tag::space, CharEncoding>, Modifiers>
{
typedef any_space<CharEncoding> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}}} // namespace boost::spirit::karma
#endif // !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
@@ -0,0 +1,168 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM)
#define BOOST_SPIRIT_CHAR_GENERATOR_SEP_07_2009_0417PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/container.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::complement> // enables ~
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace traits // classification
{
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(char_generator_id)
}
template <typename T>
struct is_char_generator : detail::has_char_generator_id<T> {};
}}}
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// The base char_parser
///////////////////////////////////////////////////////////////////////////
template <typename Derived, typename CharEncoding, typename Tag
, typename Char = typename CharEncoding::char_type, typename Attr = Char>
struct char_generator : primitive_generator<Derived>
{
typedef CharEncoding char_encoding;
typedef Tag tag;
typedef Char char_type;
struct char_generator_id;
// if Attr is unused_type, Derived must supply its own attribute
// metafunction
template <typename Context, typename Unused>
struct attribute
{
typedef Attr type;
};
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;
Attr ch = Attr();
if (!this->derived().test(traits::extract_from<Attr>(attr, context), ch, context))
return false;
return karma::detail::generate_to(sink, ch, char_encoding(), tag()) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// Requirement: g.test(attr, ch, context) -> bool
//
// attr: associated attribute
// ch: character to be generated (set by test())
// context: enclosing rule context
};
///////////////////////////////////////////////////////////////////////////
// negated_char_generator handles ~cg expressions (cg is a char_generator)
///////////////////////////////////////////////////////////////////////////
template <typename Positive>
struct negated_char_generator
: char_generator<negated_char_generator<Positive>
, typename Positive::char_encoding, typename Positive::tag>
{
negated_char_generator(Positive const& positive)
: positive(positive) {}
template <typename Attribute, typename CharParam, typename Context>
bool test(Attribute const& attr, CharParam& ch, Context& context) const
{
return !positive.test(attr, ch, context);
}
template <typename Context>
info what(Context& context) const
{
return info("not", positive.what(context));
}
Positive positive;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Positive>
struct make_negated_char_generator
{
typedef negated_char_generator<Positive> result_type;
result_type operator()(Positive const& positive) const
{
return result_type(positive);
}
};
template <typename Positive>
struct make_negated_char_generator<negated_char_generator<Positive> >
{
typedef Positive result_type;
result_type operator()(negated_char_generator<Positive> const& ncg) const
{
return ncg.positive;
}
};
}
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::complement, Elements, Modifiers>
{
typedef typename
fusion::result_of::value_at_c<Elements, 0>::type
subject;
BOOST_SPIRIT_ASSERT_MSG((
traits::is_char_generator<subject>::value
), subject_is_not_negatable, (subject));
typedef typename
detail::make_negated_char_generator<subject>::result_type
result_type;
result_type operator()(Elements const& elements, unused_type) const
{
return detail::make_negated_char_generator<subject>()(
fusion::at_c<0>(elements));
}
};
}}}
#endif
@@ -0,0 +1,27 @@
// 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_DELIMIT_FLAG_DEC_02_2009_1201PM)
#define BOOST_SPIRIT_KARMA_DELIMIT_FLAG_DEC_02_2009_1201PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
BOOST_SCOPED_ENUM_START(delimit_flag)
{
predelimit, // force predelimiting in generate_delimited()
dont_predelimit // inhibit predelimiting in generate_delimited()
};
BOOST_SCOPED_ENUM_END
}}}
#endif
@@ -0,0 +1,45 @@
// 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_DELIMIT_FEB_20_2007_1208PM)
#define BOOST_SPIRIT_KARMA_DELIMIT_FEB_20_2007_1208PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/detail/unused_delimiter.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// Do delimiting. This is equivalent to p << d. The function is a
// no-op if spirit::unused is passed as the delimiter-generator.
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Delimiter>
inline bool delimit_out(OutputIterator& sink, Delimiter const& d)
{
return d.generate(sink, unused, unused, unused);
}
template <typename OutputIterator>
inline bool delimit_out(OutputIterator&, unused_type)
{
return true;
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Delimiter>
inline bool delimit_out(OutputIterator&
, detail::unused_delimiter<Delimiter> const&)
{
return true;
}
}}}
#endif
@@ -0,0 +1,250 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/directive/buffer.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/detail/hold_any.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// execute a generator if the given Attribute type is compatible
///////////////////////////////////////////////////////////////////////////
// this gets instantiated if the Attribute type is _not_ compatible with
// the generator
template <typename Component, typename Attribute, typename Expected
, typename Enable = void>
struct alternative_generate
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const&, OutputIterator&, Context&, Delimiter const&
, Attribute const&, bool& failed)
{
failed = true;
return false;
}
};
template <typename Component>
struct alternative_generate<Component, unused_type, unused_type>
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink, Context& ctx
, Delimiter const& d, unused_type, bool&)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators succeed
return component.generate(sink, ctx, d, unused);
}
};
// this gets instantiated if there is no Attribute given for the
// alternative generator
template <typename Component, typename Expected>
struct alternative_generate<Component, unused_type, Expected>
: alternative_generate<Component, unused_type, unused_type> {};
// this gets instantiated if the generator does not expect to receive an
// Attribute (the generator is self contained).
template <typename Component, typename Attribute>
struct alternative_generate<Component, Attribute, unused_type>
: alternative_generate<Component, unused_type, unused_type> {};
// this gets instantiated if the Attribute type is compatible to the
// generator
template <typename Component, typename Attribute, typename Expected>
struct alternative_generate<Component, Attribute, Expected
, typename enable_if<
traits::compute_compatible_component<Expected, Attribute, karma::domain> >::type>
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
return call(component, sink, ctx, d, attr
, spirit::traits::not_is_variant<Attribute, karma::domain>());
}
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
return component.generate(sink, ctx, d, attr);
}
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
typedef
traits::compute_compatible_component<Expected, Attribute, domain>
component_type;
// if we got passed an empty optional, just fail generation
if (!traits::has_optional_value(attr))
return false;
// make sure, the content of the passed variant matches our
// expectations
typename traits::optional_attribute<Attribute>::type attr_ =
traits::optional_value(attr);
if (!component_type::is_compatible(spirit::traits::which(attr_)))
return false;
// returns true if any of the generators succeed
typedef typename component_type::compatible_type compatible_type;
return component.generate(sink, ctx, d
, boost::get<compatible_type>(attr_));
}
};
///////////////////////////////////////////////////////////////////////////
// alternative_generate_function: a functor supplied to fusion::any which
// will be executed for every generator in a given alternative generator
// expression
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Strict>
struct alternative_generate_function
{
alternative_generate_function(OutputIterator& sink_, Context& ctx_
, Delimiter const& d, Attribute const& attr_)
: sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
template <typename Component>
bool operator()(Component const& component)
{
typedef
typename traits::attribute_of<Component, Context>::type
expected_type;
typedef
alternative_generate<Component, Attribute, expected_type>
generate;
// wrap the given output iterator avoid output as long as one
// component fails
detail::enable_buffering<OutputIterator> buffering(sink);
bool r = false;
bool failed = false; // will be ignored
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = generate::call(component, sink, ctx, delim, attr, failed);
}
if (r)
buffering.buffer_copy();
return r;
}
// avoid double buffering
template <typename Component>
bool operator()(buffer_directive<Component> const& component)
{
typedef typename
traits::attribute_of<Component, Context>::type
expected_type;
typedef alternative_generate<
buffer_directive<Component>, Attribute, expected_type>
generate;
bool failed = false; // will be ignored
return generate::call(component, sink, ctx, delim, attr, failed);
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
Attribute const& attr;
private:
// silence MSVC warning C4512: assignment operator could not be generated
alternative_generate_function& operator= (alternative_generate_function const&);
};
// specialization for strict alternatives
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute>
struct alternative_generate_function<
OutputIterator, Context, Delimiter, Attribute, mpl::true_>
{
alternative_generate_function(OutputIterator& sink_, Context& ctx_
, Delimiter const& d, Attribute const& attr_)
: sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
template <typename Component>
bool operator()(Component const& component)
{
typedef
typename traits::attribute_of<Component, Context>::type
expected_type;
typedef
alternative_generate<Component, Attribute, expected_type>
generate;
if (failed)
return false; // give up when already failed
// wrap the given output iterator avoid output as long as one
// component fails
detail::enable_buffering<OutputIterator> buffering(sink);
bool r = false;
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = generate::call(component, sink, ctx, delim, attr, failed);
}
if (r && !failed)
{
buffering.buffer_copy();
return true;
}
return false;
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
Attribute const& attr;
bool failed;
private:
// silence MSVC warning C4512: assignment operator could not be generated
alternative_generate_function& operator= (alternative_generate_function const&);
};
}}}}
#endif
@@ -0,0 +1,74 @@
// 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_AS_STRING_DEC_18_0644PM)
#define BOOST_SPIRIT_KARMA_AS_STRING_DEC_18_0644PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// This file contains the attribute to string conversion utility. The
// utility provided also accept spirit's unused_type; all no-ops. Compiler
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Attribute>
inline typename spirit::result_of::attribute_as<T, Attribute>::type
as(Attribute const& attr)
{
return attribute_as<T, Attribute>::call(attr);
}
template <typename T>
inline unused_type as(unused_type)
{
return unused;
}
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Attribute>
inline bool valid_as(Attribute const& attr)
{
return attribute_as<T, Attribute>::is_valid(attr);
}
template <typename T>
inline bool valid_as(unused_type)
{
return true;
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
template <typename T, typename Attribute>
struct attribute_as
: traits::attribute_as<T, Attribute>
{};
template <typename T>
struct attribute_as<T, unused_type>
{
typedef unused_type type;
};
template <typename T>
struct attribute_as<T, unused_type const>
{
typedef unused_type type;
};
}}}
#endif
@@ -0,0 +1,108 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_DETAIL_ATTRIBUTES_APR_18_2010_0453PM)
#define SPIRIT_KARMA_DETAIL_ATTRIBUTES_APR_18_2010_0453PM
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/support/attributes.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Exposed, typename Transformed, typename Enable = void>
struct transform_attribute
{
typedef Transformed type;
static Transformed pre(Exposed& val)
{
return Transformed(traits::extract_from<Transformed>(val, unused));
}
// Karma only, no post() and no fail() required
};
template <typename Exposed, typename Transformed>
struct transform_attribute<boost::optional<Exposed> const, Transformed
, typename disable_if<is_same<boost::optional<Exposed>, Transformed> >::type>
{
typedef Transformed const& type;
static Transformed const& pre(boost::optional<Exposed> const& val)
{
return boost::get<Transformed>(val);
}
};
template <typename Attribute>
struct transform_attribute<Attribute const, Attribute>
{
typedef Attribute const& type;
static Attribute const& pre(Attribute const& val) { return val; }
// Karma only, no post() and no fail() required
};
// reference types need special handling
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed&, Transformed>
: transform_attribute<Exposed, Transformed>
{};
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed const&, Transformed>
: transform_attribute<Exposed const, Transformed>
{};
template <typename Attribute>
struct transform_attribute<Attribute const&, Attribute>
: transform_attribute<Attribute const, Attribute>
{};
// unused_type needs some special handling as well
template <>
struct transform_attribute<unused_type, unused_type>
{
typedef unused_type type;
static unused_type pre(unused_type) { return unused; }
};
template <>
struct transform_attribute<unused_type const, unused_type>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<unused_type, Attribute>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<unused_type const, Attribute>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<Attribute, unused_type>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<Attribute const, unused_type>
: transform_attribute<unused_type, unused_type>
{};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed, Transformed, karma::domain>
: karma::transform_attribute<Exposed, Transformed>
{};
}}}
#endif
@@ -0,0 +1,75 @@
// 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_DEFAULT_WIDTH_APR_07_2009_0912PM)
#define BOOST_SPIRIT_KARMA_DEFAULT_WIDTH_APR_07_2009_0912PM
#if defined(_MSC_VER)
#pragma once
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_FIELD_LENGTH specifies the default field length
// to be used for padding.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_FIELD_LENGTH)
#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 10
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH specifies the default maximal field
// length to be used for the maxwidth directive.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH)
#define BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH 10
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_COLUMNS specifies the default number of columns to
// be used with the columns directive.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_COLUMNS)
#define BOOST_KARMA_DEFAULT_COLUMNS 5
#endif
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
struct default_width
{
operator int() const
{
return BOOST_KARMA_DEFAULT_FIELD_LENGTH;
}
};
///////////////////////////////////////////////////////////////////////////
struct default_max_width
{
operator int() const
{
return BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH;
}
};
///////////////////////////////////////////////////////////////////////////
struct default_columns
{
operator int() const
{
return BOOST_KARMA_DEFAULT_COLUMNS;
}
};
}}}}
#endif
@@ -0,0 +1,30 @@
// 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_DETAIL_ENABLE_LIT_JAN_06_2011_1009PM)
#define BOOST_SPIRIT_KARMA_DETAIL_ENABLE_LIT_JAN_06_2011_1009PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit
{
// enables lazy lit(...) for karma
template <>
struct use_lazy_terminal<karma::domain, tag::lit, 1>
: mpl::true_ {};
}}
#endif
@@ -0,0 +1,274 @@
// 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_EXTRACT_FROM_SEP_30_2009_0732AM)
#define BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/ref.hpp>
#include <boost/optional.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// This file contains attribute extraction utilities. The utilities
// provided also accept spirit's unused_type; all no-ops. Compiler
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
// extract first and second element of a fusion sequence
template <typename T>
struct add_const_ref
: add_reference<typename add_const<T>::type>
{};
template <typename T, int N>
struct value_at_c
: add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
{};
}
// This is the default case: the plain attribute values
template <typename Attribute, typename Exposed, typename Enable/*= void*/>
struct extract_from_attribute
{
typedef typename traits::one_element_sequence<Attribute>::type
is_one_element_sequence;
typedef typename mpl::eval_if<
is_one_element_sequence
, detail::value_at_c<Attribute, 0>
, mpl::identity<Attribute const&>
>::type type;
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_)
{
return attr;
}
// This handles the case where the attribute is a single element fusion
// sequence. We silently extract the only element and treat it as the
// attribute to generate output from.
template <typename Context>
static type call(Attribute const& attr, Context& ctx, mpl::true_)
{
return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
}
template <typename Context>
static type call(Attribute const& attr, Context& ctx)
{
return call(attr, ctx, is_one_element_sequence());
}
};
// This handles optional attributes.
template <typename Attribute, typename Exposed>
struct extract_from_attribute<boost::optional<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(boost::optional<Attribute> const& attr, Context& ctx)
{
return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
}
};
template <typename Attribute, typename Exposed>
struct extract_from_attribute<boost::optional<Attribute const>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(boost::optional<Attribute const> const& attr, Context& ctx)
{
return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
}
};
// This handles attributes wrapped inside a boost::ref().
template <typename Attribute, typename Exposed>
struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
{
return extract_from<Exposed>(attr.get(), ctx);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Attribute, typename Exposed, typename Enable>
struct extract_from_container
{
typedef typename traits::container_value<Attribute const>::type
value_type;
typedef typename is_convertible<value_type, Exposed>::type
is_convertible_to_value_type;
typedef typename mpl::if_<
mpl::or_<
is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
, Exposed const&, Exposed
>::type type;
// handle case where container value type is convertible to result type
// we simply return the front element of the container
template <typename Context, typename Pred>
static type call(Attribute const& attr, Context&, mpl::true_, Pred)
{
// return first element from container
typedef typename traits::container_iterator<Attribute const>::type
iterator_type;
iterator_type it = traits::begin(attr);
type result = *it;
++it;
return result;
}
// handle strings
template <typename Iterator>
static void append_to_string(Exposed& result, Iterator begin, Iterator end)
{
for (Iterator i = begin; i != end; ++i)
push_back(result, *i);
}
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_, mpl::true_)
{
typedef typename char_type_of<Attribute>::type char_type;
Exposed result;
append_to_string(result, traits::get_begin<char_type>(attr)
, traits::get_end<char_type>(attr));
return result;
}
// everything else gets just passed through
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_, mpl::false_)
{
return type(attr);
}
template <typename Context>
static type call(Attribute const& attr, Context& ctx)
{
typedef typename mpl::and_<
traits::is_string<Exposed>, traits::is_string<Attribute>
>::type handle_strings;
// return first element from container
return call(attr, ctx, is_convertible_to_value_type()
, handle_strings());
}
};
template <typename Attribute>
struct extract_from_container<Attribute, Attribute>
{
typedef Attribute const& type;
template <typename Context>
static type call(Attribute const& attr, Context&)
{
return attr;
}
};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
// overload for non-container attributes
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx, mpl::false_)
{
return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
}
// overload for containers (but not for variants or optionals
// holding containers)
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx, mpl::true_)
{
return extract_from_container<Attribute, Exposed>::call(attr, ctx);
}
}
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx
#if (defined(__GNUC__) && (__GNUC__ < 4)) || \
(defined(__APPLE__) && defined(__INTEL_COMPILER))
, typename enable_if<traits::not_is_unused<Attribute> >::type*
#endif
)
{
typedef typename mpl::and_<
traits::is_container<Attribute>
, traits::not_is_variant<Attribute>
, traits::not_is_optional<Attribute>
>::type is_not_wrapped_container;
return detail::extract_from<Exposed>(attr, ctx
, is_not_wrapped_container());
}
template <typename Exposed, typename Context>
inline unused_type extract_from(unused_type, Context&)
{
return unused;
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
template <typename Exposed, typename Attribute>
struct extract_from
: mpl::if_<
mpl::and_<
traits::is_container<Attribute>
, traits::not_is_variant<Attribute>
, traits::not_is_optional<Attribute> >
, traits::extract_from_container<Attribute, Exposed>
, traits::extract_from_attribute<Attribute, Exposed> >::type
{};
template <typename Exposed>
struct extract_from<Exposed, unused_type>
{
typedef unused_type type;
};
template <typename Exposed>
struct extract_from<Exposed, unused_type const>
{
typedef unused_type type;
};
}}}
#endif
@@ -0,0 +1,60 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0249PM)
#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0249PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/config.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename OutputIterator, typename Context, typename Delimiter>
struct fail_function
{
typedef Context context_type;
fail_function(OutputIterator& sink_, Context& context_
, Delimiter const& delim_)
: sink(sink_), ctx(context_), delim(delim_)
{}
template <typename Component, typename Attribute>
bool operator()(Component const& component, Attribute const& attr) const
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators fail
return !component.generate(sink, ctx, delim, attr);
}
template <typename Component>
bool operator()(Component const& component) const
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators fail
return !component.generate(sink, ctx, delim, unused);
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
private:
// silence MSVC warning C4512: assignment operator could not be generated
fail_function& operator= (fail_function const&);
};
}}}}
#endif
@@ -0,0 +1,131 @@
// 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_DETAIL_GENERATE_FEB_20_2007_0959AM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_FEB_20_2007_0959AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/delimit_flag.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable = void>
struct generate_impl
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr>
struct generate_impl<Expr
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
template <typename OutputIterator>
static bool call(
OutputIterator& target_sink
, Expr const& expr)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
// wrap user supplied iterator into our own output iterator
output_iterator<OutputIterator
, mpl::int_<properties::value> > sink(target_sink);
return compile<karma::domain>(expr).
generate(sink, unused, unused, unused);
}
template <typename OutputIterator, typename Properties>
static bool call(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr)
{
return compile<karma::domain>(expr).
generate(sink, unused, unused, unused);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable = void>
struct generate_delimited_impl
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr>
struct generate_delimited_impl<Expr
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
template <typename OutputIterator, typename Delimiter>
static bool call(
OutputIterator& target_sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
typedef traits::properties_of<
typename result_of::compile<karma::domain, Delimiter>::type
> delimiter_properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value | delimiter_properties::value>
> sink(target_sink);
return call(sink, expr, delimiter, pre_delimit);
}
template <typename OutputIterator, typename Properties
, typename Delimiter>
static bool call(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the delimiter is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typename result_of::compile<karma::domain, Delimiter>::type const
delimiter_ = compile<karma::domain>(delimiter);
if (pre_delimit == delimit_flag::predelimit &&
!karma::delimit_out(sink, delimiter_))
{
return false;
}
return compile<karma::domain>(expr).
generate(sink, unused, delimiter_, unused);
}
};
}}}}
#endif
@@ -0,0 +1,63 @@
// 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_DETAIL_GENERATE_AUTO_DEC_01_2009_0743PM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_AUTO_DEC_01_2009_0743PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/spirit/home/karma/auto/create_generator.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/and.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct generate_impl<Expr
, typename enable_if<
mpl::and_<
traits::meta_create_exists<karma::domain, Expr>
, mpl::not_<traits::matches<karma::domain, Expr> > >
>::type>
{
template <typename OutputIterator>
static bool call(
OutputIterator& sink
, Expr const& expr)
{
return karma::generate(sink, create_generator<Expr>(), expr);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct generate_delimited_impl<Expr
, typename enable_if<
mpl::and_<
traits::meta_create_exists<karma::domain, Expr>
, mpl::not_<traits::matches<karma::domain, Expr> > >
>::type>
{
template <typename OutputIterator, typename Delimiter>
static bool call(
OutputIterator& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
return karma::generate_delimited(
sink, create_generator<Expr>(), delimiter, pre_delimit, expr);
}
};
}}}}
#endif
@@ -0,0 +1,67 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DETAIL_GENERATE_TO_FEB_20_2007_0417PM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_TO_FEB_20_2007_0417PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// These utility functions insert the given parameter into the supplied
// output iterator.
// If the attribute is spirit's unused_type, this is a no_op.
///////////////////////////////////////////////////////////////////////////
template <
typename OutputIterator, typename Attribute, typename CharEncoding
, typename Tag>
inline bool
generate_to(OutputIterator& sink, Attribute const& p, CharEncoding, Tag)
{
*sink = spirit::char_class::convert<CharEncoding>::to(Tag(), p);
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename Attribute>
inline bool
generate_to(OutputIterator& sink, Attribute const& p, unused_type, unused_type)
{
*sink = p;
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename CharEncoding, typename Tag>
inline bool generate_to(OutputIterator&, unused_type, CharEncoding, Tag)
{
return true;
}
template <typename OutputIterator, typename Attribute>
inline bool
generate_to(OutputIterator& sink, Attribute const& p)
{
*sink = p;
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator>
inline bool generate_to(OutputIterator&, unused_type)
{
return true;
}
}}}} // namespace boost::spirit::karma::detail
#endif // KARMA_CORE_DETAIL_INSERT_TO_HPP
@@ -0,0 +1,29 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_GET_CASETAG_JANUARY_19_2009_1107AM)
#define BOOST_SPIRIT_KARMA_GET_CASETAG_JANUARY_19_2009_1107AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/identity.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Modifiers, bool case_modifier = false>
struct get_casetag : mpl::identity<unused_type> {};
template <typename Modifiers>
struct get_casetag<Modifiers, true>
: mpl::if_<has_modifier<Modifiers, tag::char_code_base<tag::lower> >
, tag::lower, tag::upper> {};
}}}}
#endif
@@ -0,0 +1,33 @@
// 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_GET_STRICTTAG_APR_22_2010_1007AM)
#define BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/or.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
// the default mode for Karma is 'relaxed'
template <
typename Modifiers
, typename StrictModifier = typename mpl::or_<
has_modifier<Modifiers, tag::strict>
, has_modifier<Modifiers, tag::relaxed> >::type>
struct get_stricttag : mpl::false_ {};
// strict mode is enforced only when tag::strict is on the modifiers list
template <typename Modifiers>
struct get_stricttag<Modifiers, mpl::true_>
: has_modifier<Modifiers, tag::strict> {};
}}}}
#endif
@@ -0,0 +1,98 @@
// 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(SPIRIT_KARMA_INDIRECT_ITERATOR_JAN_19_2011_0814PM)
#define SPIRIT_KARMA_INDIRECT_ITERATOR_JAN_19_2011_0814PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/iterator/iterator_facade.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////
// This is a wrapper for any iterator allowing to pass a reference of it
// to the components of the sequence
template <typename Iterator>
class indirect_iterator
: public boost::iterator_facade<
indirect_iterator<Iterator>
, typename boost::detail::iterator_traits<Iterator>::value_type
, boost::forward_traversal_tag
, typename boost::detail::iterator_traits<Iterator>::reference>
{
typedef typename boost::detail::iterator_traits<Iterator>::value_type
base_value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference
base_reference_type;
typedef boost::iterator_facade<
indirect_iterator<Iterator>, base_value_type
, boost::forward_traversal_tag, base_reference_type
> base_type;
public:
indirect_iterator(Iterator& iter)
: iter_(&iter)
{}
indirect_iterator(indirect_iterator const& iter)
: iter_(iter.iter_)
{}
private:
friend class boost::iterator_core_access;
void increment()
{
++*iter_;
}
bool equal(indirect_iterator const& other) const
{
return *iter_ == *other.iter_;
}
base_reference_type dereference() const
{
return **iter_;
}
private:
Iterator* iter_;
};
}}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
template <typename Iterator>
struct make_indirect_iterator
{
typedef karma::detail::indirect_iterator<Iterator> type;
};
template <typename Iterator>
struct make_indirect_iterator<karma::detail::indirect_iterator<Iterator> >
{
typedef karma::detail::indirect_iterator<Iterator> type;
};
template <>
struct make_indirect_iterator<unused_type const*>
{
typedef unused_type const* type;
};
template <typename Iterator>
struct make_indirect_iterator<Iterator const&>
: make_indirect_iterator<Iterator const>
{};
}}}
#endif
@@ -0,0 +1,644 @@
// 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_OUTPUT_ITERATOR_MAY_26_2007_0506PM)
#define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <iterator>
#include <vector>
#include <algorithm>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/mpl/if.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
#include <boost/spirit/home/support/unused.hpp>
#if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
#include <boost/spirit/home/support/char_encoding/unicode.hpp>
#endif
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// This class is used to keep track of the current position in the output.
///////////////////////////////////////////////////////////////////////////
class position_sink
{
public:
position_sink() : count(0), line(1), column(1) {}
void tidy() { count = 0; line = 1; column = 1; }
template <typename T>
void output(T const& value)
{
++count;
if (value == '\n') {
++line;
column = 1;
}
else {
++column;
}
}
std::size_t get_count() const { return count; }
std::size_t get_line() const { return line; }
std::size_t get_column() const { return column; }
private:
std::size_t count;
std::size_t line;
std::size_t column;
};
///////////////////////////////////////////////////////////////////////////
struct position_policy
{
position_policy() {}
position_policy(position_policy const& rhs)
: track_position_data(rhs.track_position_data) {}
template <typename T>
void output(T const& value)
{
// track position in the output
track_position_data.output(value);
}
// return the current count in the output
std::size_t get_out_count() const
{
return track_position_data.get_count();
}
// return the current line in the output
std::size_t get_line() const
{
return track_position_data.get_line();
}
// return the current column in the output
std::size_t get_column() const
{
return track_position_data.get_column();
}
private:
position_sink track_position_data; // for position tracking
};
struct no_position_policy
{
no_position_policy() {}
no_position_policy(no_position_policy const&) {}
template <typename T>
void output(T const& /*value*/) {}
};
///////////////////////////////////////////////////////////////////////////
// This class is used to count the number of characters streamed into the
// output.
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
class counting_sink : boost::noncopyable
{
public:
counting_sink(OutputIterator& sink_, std::size_t count_ = 0
, bool enabled = true)
: count(count_), initial_count(count), prev_count(0), sink(sink_)
{
prev_count = sink.chain_counting(enabled ? this : NULL);
}
~counting_sink()
{
if (prev_count) // propagate count
prev_count->update_count(count-initial_count);
sink.chain_counting(prev_count);
}
void output()
{
++count;
}
std::size_t get_count() const { return count; }
// propagate count from embedded counters
void update_count(std::size_t c)
{
count += c;
}
private:
std::size_t count;
std::size_t initial_count;
counting_sink* prev_count; // previous counter in chain
OutputIterator& sink;
};
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct counting_policy
{
public:
counting_policy() : count(NULL) {}
counting_policy(counting_policy const& rhs) : count(rhs.count) {}
// functions related to counting
counting_sink<OutputIterator>* chain_counting(
counting_sink<OutputIterator>* count_data)
{
counting_sink<OutputIterator>* prev_count = count;
count = count_data;
return prev_count;
}
template <typename T>
void output(T const&)
{
// count characters, if appropriate
if (NULL != count)
count->output();
}
private:
counting_sink<OutputIterator>* count; // for counting
};
struct no_counting_policy
{
no_counting_policy() {}
no_counting_policy(no_counting_policy const&) {}
template <typename T>
void output(T const& /*value*/) {}
};
///////////////////////////////////////////////////////////////////////////
// The following classes are used to intercept the output into a buffer
// allowing to do things like alignment, character escaping etc.
///////////////////////////////////////////////////////////////////////////
class buffer_sink : boost::noncopyable
{
// wchar_t is only 16-bits on Windows. If BOOST_SPIRIT_UNICODE is
// defined, the character type is 32-bits wide so we need to make
// sure the buffer is at least that wide.
#if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
typedef spirit::char_encoding::unicode::char_type buffer_char_type;
#else
typedef wchar_t buffer_char_type;
#endif
public:
buffer_sink()
: width(0) {}
~buffer_sink()
{
tidy();
}
void enable(std::size_t width_)
{
tidy(); // release existing buffer
width = (width_ == std::size_t(-1)) ? 0 : width_;
buffer.reserve(width);
}
void tidy()
{
buffer.clear();
width = 0;
}
template <typename T>
void output(T const& value)
{
BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(buffer_char_type));
buffer.push_back(value);
}
template <typename OutputIterator_>
bool copy(OutputIterator_& sink, std::size_t maxwidth) const
{
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable: 4267)
#endif
typename std::basic_string<buffer_char_type>::const_iterator end =
buffer.begin() + (std::min)(buffer.size(), maxwidth);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
std::copy(buffer.begin(), end, sink);
return true;
}
template <typename RestIterator>
bool copy_rest(RestIterator& sink, std::size_t start_at) const
{
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable: 4267)
#endif
typename std::basic_string<buffer_char_type>::const_iterator begin =
buffer.begin() + (std::min)(buffer.size(), start_at);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
std::copy(begin, buffer.end(), sink);
return true;
}
std::size_t buffer_size() const
{
return buffer.size();
}
private:
std::size_t width;
std::basic_string<buffer_char_type> buffer;
};
///////////////////////////////////////////////////////////////////////////
struct buffering_policy
{
public:
buffering_policy() : buffer(NULL) {}
buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
// functions related to buffering
buffer_sink* chain_buffering(buffer_sink* buffer_data)
{
buffer_sink* prev_buffer = buffer;
buffer = buffer_data;
return prev_buffer;
}
template <typename T>
bool output(T const& value)
{
// buffer characters, if appropriate
if (NULL != buffer) {
buffer->output(value);
return false;
}
return true;
}
bool has_buffer() const { return NULL != buffer; }
private:
buffer_sink* buffer;
};
struct no_buffering_policy
{
no_buffering_policy() {}
no_buffering_policy(no_counting_policy const&) {}
template <typename T>
bool output(T const& /*value*/)
{
return true;
}
bool has_buffer() const { return false; }
};
///////////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename OutputIterator>
struct enable_buffering;
template <typename OutputIterator, typename Properties
, typename Derived = unused_type>
class output_iterator;
///////////////////////////////////////////////////////////////////////////
template <typename Buffering, typename Counting, typename Tracking>
struct output_iterator_base : Buffering, Counting, Tracking
{
typedef Buffering buffering_policy;
typedef Counting counting_policy;
typedef Tracking tracking_policy;
output_iterator_base() {}
output_iterator_base(output_iterator_base const& rhs)
: buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
{}
template <typename T>
bool output(T const& value)
{
this->counting_policy::output(value);
this->tracking_policy::output(value);
return this->buffering_policy::output(value);
}
};
template <typename Buffering, typename Counting, typename Tracking>
struct disabling_output_iterator : Buffering, Counting, Tracking
{
typedef Buffering buffering_policy;
typedef Counting counting_policy;
typedef Tracking tracking_policy;
disabling_output_iterator() : do_output(true) {}
disabling_output_iterator(disabling_output_iterator const& rhs)
: buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
, do_output(rhs.do_output)
{}
template <typename T>
bool output(T const& value)
{
if (!do_output)
return false;
this->counting_policy::output(value);
this->tracking_policy::output(value);
return this->buffering_policy::output(value);
}
bool do_output;
};
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Derived>
struct make_output_iterator
{
// get the most derived type of this class
typedef typename mpl::if_<
traits::not_is_unused<Derived>, Derived
, output_iterator<OutputIterator, Properties, Derived>
>::type most_derived_type;
enum { properties = Properties::value };
typedef typename mpl::if_c<
(properties & generator_properties::tracking) ? true : false
, position_policy, no_position_policy
>::type tracking_type;
typedef typename mpl::if_c<
(properties & generator_properties::buffering) ? true : false
, buffering_policy, no_buffering_policy
>::type buffering_type;
typedef typename mpl::if_c<
(properties & generator_properties::counting) ? true : false
, counting_policy<most_derived_type>, no_counting_policy
>::type counting_type;
typedef typename mpl::if_c<
(properties & generator_properties::disabling) ? true : false
, disabling_output_iterator<buffering_type, counting_type, tracking_type>
, output_iterator_base<buffering_type, counting_type, tracking_type>
>::type type;
};
///////////////////////////////////////////////////////////////////////////
// Karma uses an output iterator wrapper for all output operations. This
// is necessary to avoid the dreaded 'scanner business' problem, i.e. the
// dependency of rules and grammars on the used output iterator.
//
// By default the user supplied output iterator is wrapped inside an
// instance of this internal output_iterator class.
//
// This output_iterator class normally just forwards to the embedded user
// supplied iterator. But it is possible to enable additional functionality
// on demand, such as counting, buffering, and position tracking.
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Derived>
class output_iterator
: public make_output_iterator<OutputIterator, Properties, Derived>::type
{
private:
// base iterator type
typedef typename make_output_iterator<
OutputIterator, Properties, Derived>::type base_iterator;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
explicit output_iterator(OutputIterator& sink_)
: sink(&sink_)
{}
output_iterator(output_iterator const& rhs)
: base_iterator(rhs), sink(rhs.sink)
{}
output_iterator& operator*() { return *this; }
output_iterator& operator++()
{
if (!this->base_iterator::has_buffer())
++(*sink); // increment only if not buffering
return *this;
}
output_iterator operator++(int)
{
if (!this->base_iterator::has_buffer()) {
output_iterator t(*this);
++(*sink);
return t;
}
return *this;
}
#if defined(BOOST_MSVC)
// 'argument' : conversion from '...' to '...', possible loss of data
#pragma warning (push)
#pragma warning (disable: 4244)
#endif
template <typename T>
void operator=(T const& value)
{
if (this->base_iterator::output(value))
*(*sink) = value;
}
#if defined(BOOST_MSVC)
#pragma warning (pop)
#endif
// plain output iterators are considered to be good all the time
bool good() const { return true; }
// allow to access underlying output iterator
OutputIterator& base() { return *sink; }
protected:
// this is the wrapped user supplied output iterator
OutputIterator* sink;
};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Elem, typename Traits, typename Properties>
class output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
: public output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
, output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties> >
{
private:
typedef output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
, output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
> base_type;
typedef karma::ostream_iterator<T, Elem, Traits> base_iterator_type;
typedef std::basic_ostream<Elem, Traits> ostream_type;
public:
output_iterator(base_iterator_type& sink)
: base_type(sink) {}
ostream_type& get_ostream() { return (*this->sink).get_ostream(); }
ostream_type const& get_ostream() const { return (*this->sink).get_ostream(); }
// expose good bit of underlying stream object
bool good() const { return (*this->sink).get_ostream().good(); }
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe enabling of character counting in the
// output iterator
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct enable_counting
{
enable_counting(OutputIterator& sink_, std::size_t count = 0)
: count_data(sink_, count) {}
// get number of characters counted since last enable
std::size_t count() const
{
return count_data.get_count();
}
private:
counting_sink<OutputIterator> count_data; // for counting
};
template <typename OutputIterator>
struct disable_counting
{
disable_counting(OutputIterator& sink_)
: count_data(sink_, 0, false) {}
private:
counting_sink<OutputIterator> count_data;
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe enabling of character buffering in the
// output iterator
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct enable_buffering
{
enable_buffering(OutputIterator& sink_
, std::size_t width = std::size_t(-1))
: sink(sink_), prev_buffer(NULL), enabled(false)
{
buffer_data.enable(width);
prev_buffer = sink.chain_buffering(&buffer_data);
enabled = true;
}
~enable_buffering()
{
disable();
}
// reset buffer chain to initial state
void disable()
{
if (enabled) {
BOOST_VERIFY(&buffer_data == sink.chain_buffering(prev_buffer));
enabled = false;
}
}
// copy to the underlying sink whatever is in the local buffer
bool buffer_copy(std::size_t maxwidth = std::size_t(-1)
, bool disable_ = true)
{
if (disable_)
disable();
return buffer_data.copy(sink, maxwidth) && sink.good();
}
// return number of characters stored in the buffer
std::size_t buffer_size() const
{
return buffer_data.buffer_size();
}
// copy to the remaining characters to the specified sink
template <typename RestIterator>
bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0) const
{
return buffer_data.copy_rest(sink, start_at);
}
// copy the contents to the given output iterator
template <typename OutputIterator_>
bool buffer_copy_to(OutputIterator_& sink
, std::size_t maxwidth = std::size_t(-1)) const
{
return buffer_data.copy(sink, maxwidth);
}
private:
OutputIterator& sink;
buffer_sink buffer_data; // for buffering
buffer_sink* prev_buffer; // previous buffer in chain
bool enabled;
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe disabling of output
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct disable_output
{
disable_output(OutputIterator& sink_)
: sink(sink_), prev_do_output(sink.do_output)
{
sink.do_output = false;
}
~disable_output()
{
sink.do_output = prev_do_output;
}
OutputIterator& sink;
bool prev_do_output;
};
///////////////////////////////////////////////////////////////////////////
template <typename Sink>
bool sink_is_good(Sink const&)
{
return true; // the general case is always good
}
template <typename OutputIterator, typename Derived>
bool sink_is_good(output_iterator<OutputIterator, Derived> const& sink)
{
return sink.good(); // our own output iterators are handled separately
}
}}}}
#endif
@@ -0,0 +1,392 @@
/*=============================================================================
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2001-2011 Joel de Guzman
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(SPIRIT_PASS_CONTAINER_MAR_15_2009_0114PM)
#define SPIRIT_PASS_CONTAINER_MAR_15_2009_0114PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/detail/hold_any.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/deduce_sequence.hpp>
#include <boost/mpl/print.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
// Helper meta-function allowing to evaluate weak substitutability and
// negate the result if the predicate (Sequence) is not true
template <typename Sequence, typename Attribute, typename ValueType>
struct negate_weak_substitute_if_not
: mpl::if_<
Sequence
, typename traits::is_weak_substitute<Attribute, ValueType>::type
, typename mpl::not_<
traits::is_weak_substitute<Attribute, ValueType>
>::type>
{};
// pass_through_container: utility to check decide whether a provided
// container attribute needs to be passed through to the current component
// or of we need to split the container by passing along instances of its
// value type
// if the expected attribute of the current component is neither a Fusion
// sequence nor a container, we will pass through the provided container
// only if its value type is not compatible with the component
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename Enable = void>
struct pass_through_container_base
: negate_weak_substitute_if_not<Sequence, ValueType, Attribute>
{};
// Specialization for fusion sequences, in this case we check whether all
// the types in the sequence are convertible to the lhs attribute.
//
// We return false if the rhs attribute itself is a fusion sequence, which
// is compatible with the LHS sequence (we want to pass through this
// attribute without it being split apart).
template <typename Container, typename ValueType, typename Attribute
, typename Sequence = mpl::true_>
struct not_compatible_element
: mpl::and_<
negate_weak_substitute_if_not<Sequence, Container, Attribute>
, negate_weak_substitute_if_not<Sequence, ValueType, Attribute> >
{};
// If the value type of the container is not a Fusion sequence, we pass
// through the container if each of the elements of the Attribute
// sequence is compatible with either the container or its value type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
, bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
struct pass_through_container_fusion_sequence
{
typedef typename mpl::find_if<
Attribute, not_compatible_element<Container, ValueType, mpl::_1>
>::type iter;
typedef typename mpl::end<Attribute>::type end;
typedef typename is_same<iter, end>::type type;
};
// If both, the Attribute and the value type of the provided container
// are Fusion sequences, we pass the container only if the two
// sequences are not compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence, true>
{
typedef typename mpl::find_if<
Attribute
, not_compatible_element<Container, ValueType, mpl::_1, Sequence>
>::type iter;
typedef typename mpl::end<Attribute>::type end;
typedef typename is_same<iter, end>::type type;
};
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_base<Container, ValueType, Attribute
, Sequence
, typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
: pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence>
{};
// Specialization for containers
//
// If the value type of the attribute of the current component is not
// a Fusion sequence, we have to pass through the provided container if
// both are compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename AttributeValueType
, bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
struct pass_through_container_container
: mpl::or_<
traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<Container, AttributeValueType> >
{};
// If the value type of the exposed container attribute is a Fusion
// sequence, we use the already existing logic for those.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename AttributeValueType>
struct pass_through_container_container<
Container, ValueType, Attribute, Sequence, AttributeValueType, true>
: pass_through_container_fusion_sequence<
Container, ValueType, AttributeValueType, Sequence>
{};
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_base<Container, ValueType, Attribute
, Sequence
, typename enable_if<traits::is_container<Attribute> >::type>
: detail::pass_through_container_container<
Container, ValueType, Attribute, Sequence
, typename traits::container_value<Attribute>::type>
{};
// Specialization for exposed optional attributes
//
// If the type embedded in the exposed optional is not a Fusion
// sequence we pass through the container attribute if it is compatible
// either to the optionals embedded type or to the containers value
// type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
, bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
struct pass_through_container_optional
: mpl::or_<
traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<ValueType, Attribute> >
{};
// If the embedded type of the exposed optional attribute is a Fusion
// sequence, we use the already existing logic for those.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_optional<
Container, ValueType, Attribute, Sequence, true>
: pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence>
{};
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container
: pass_through_container_base<Container, ValueType, Attribute, Sequence>
{};
// Handle optional attributes
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, ValueType, boost::optional<Attribute>, Sequence>
: pass_through_container_optional<
Container, ValueType, Attribute, Sequence>
{};
// If both, the containers value type and the exposed attribute type are
// optionals we are allowed to pass through the container only if the
// embedded types of those optionals are not compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, boost::optional<ValueType>, boost::optional<Attribute>
, Sequence>
: mpl::not_<traits::is_weak_substitute<ValueType, Attribute> >
{};
// Specialization for exposed variant attributes
//
// We pass through the container attribute if at least one of the embedded
// types in the variant requires to pass through the attribute
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template <typename Container, typename ValueType, typename Sequence
, typename T>
struct pass_through_container<Container, ValueType, boost::variant<T>
, Sequence>
: pass_through_container<Container, ValueType, T, Sequence>
{};
template <typename Container, typename ValueType, typename Sequence
, typename T0, typename ...TN>
struct pass_through_container<Container, ValueType
, boost::variant<T0, TN...>, Sequence>
: mpl::bool_<pass_through_container<
Container, ValueType, T0, Sequence
>::type::value || pass_through_container<
Container, ValueType, boost::variant<TN...>, Sequence
>::type::value>
{};
#else
#define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
pass_through_container<Container, ValueType, \
BOOST_PP_CAT(T, N), Sequence>::type::value || \
/***/
// make sure unused variant parameters do not affect the outcome
template <typename Container, typename ValueType, typename Sequence>
struct pass_through_container<Container, ValueType
, boost::detail::variant::void_, Sequence>
: mpl::false_
{};
template <typename Container, typename ValueType, typename Sequence
, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct pass_through_container<Container, ValueType
, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
: mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
, BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
{};
#undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
#endif
}}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// forwarding customization point for domain karma::domain
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, ValueType, Attribute, Sequence, karma::domain>
: karma::detail::pass_through_container<
Container, ValueType, Attribute, Sequence>
{};
}}}
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Iterator>
struct pass_container_base
{
pass_container_base(Iterator begin, Iterator end)
: iter(begin), end(end)
{}
mutable Iterator iter;
mutable Iterator end;
};
template <typename Iterator>
struct pass_container_base<Iterator&>
{
pass_container_base(Iterator& begin, Iterator& end)
: iter(begin), end(end)
{}
Iterator& iter;
Iterator& end;
};
///////////////////////////////////////////////////////////////////////////
// This function handles the case where the attribute (Attr) given
// to the sequence is an STL container. This is a wrapper around F.
// The function F does the actual generating.
template <typename F, typename Attr, typename Iterator, typename Sequence>
struct pass_container : pass_container_base<Iterator>
{
typedef pass_container_base<Iterator> base_type;
typedef typename F::context_type context_type;
pass_container(F const& f, Iterator begin, Iterator end)
: base_type(begin, end)
, f(f)
{}
bool is_at_end() const
{
return traits::compare(this->iter, this->end);
}
void next()
{
traits::next(this->iter);
}
// this is for the case when the current element expects an attribute
// which is taken from the next entry in the container
template <typename Component>
bool dispatch_container(Component const& component, mpl::false_) const
{
// get the next value to generate from container
if (!is_at_end() && !f(component, traits::deref(this->iter)))
{
// needs to return false as long as everything is ok
traits::next(this->iter);
return false;
}
// either no elements available any more or generation failed
return true;
}
// this is for the case when the current element is able to handle an
// attribute which is a container itself, this element will push its
// data directly into the attribute container
template <typename Component>
bool dispatch_container(Component const& component, mpl::true_) const
{
return f(component, make_iterator_range(this->iter, this->end));
}
///////////////////////////////////////////////////////////////////////
// this is for the case when the current element doesn't expect an
// attribute
template <typename Component>
bool dispatch_attribute(Component const& component, mpl::false_) const
{
return f(component, unused);
}
// the current element expects an attribute
template <typename Component>
bool dispatch_attribute(Component const& component, mpl::true_) const
{
typedef typename traits::container_value<Attr>::type value_type;
typedef typename
traits::attribute_of<Component, context_type>::type
lhs_attribute;
// this predicate detects, whether the value type of the container
// attribute is a substitute for the attribute of the current
// element
typedef mpl::and_<
traits::handles_container<Component, Attr, context_type>
, traits::pass_through_container<
Attr, value_type, lhs_attribute, Sequence, karma::domain>
> predicate;
return dispatch_container(component, predicate());
}
// Dispatches to dispatch_main depending on the attribute type
// of the Component
template <typename Component>
bool operator()(Component const& component) const
{
// we need to dispatch depending on the type of the attribute
// of the current element (component). If this is has no attribute
// we shouldn't use an element of the container but unused_type
// instead
typedef traits::not_is_unused<
typename traits::attribute_of<Component, context_type>::type
> predicate;
return dispatch_attribute(component, predicate());
}
F f;
private:
// silence MSVC warning C4512: assignment operator could not be generated
pass_container& operator= (pass_container const&);
};
}}}}
#endif
@@ -0,0 +1,76 @@
// 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_STRING_COMPARE_AUG_08_2009_0756PM)
#define BOOST_SPIRIT_KARMA_STRING_COMPARE_AUG_08_2009_0756PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <string>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/range/iterator_range.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Char>
bool string_compare(Char const* attr, Char const* lit)
{
Char ch_attr = *attr;
Char ch_lit = *lit;
while (!!ch_lit && !!ch_attr)
{
if (ch_attr != ch_lit)
return false;
ch_attr = *++attr;
ch_lit = *++lit;
}
return !ch_lit && !ch_attr;
}
template <typename Char>
bool string_compare(Char const* attr, Char const* lit, unused_type, unused_type)
{
return string_compare(attr, lit);
}
template <typename Char>
bool string_compare(unused_type, Char const*, unused_type, unused_type)
{
return true;
}
template <typename Char, typename CharEncoding, typename Tag>
bool string_compare(Char const* attr, Char const* lit, CharEncoding, Tag)
{
Char ch_attr = *attr;
Char ch_lit = spirit::char_class::convert<CharEncoding>::to(Tag(), *lit);
while (!!ch_lit && !!ch_attr)
{
if (ch_attr != ch_lit)
return false;
ch_attr = *++attr;
ch_lit = spirit::char_class::convert<CharEncoding>::to(Tag(), *++lit);
}
return !ch_lit && !ch_attr;
}
template <typename Char, typename CharEncoding, typename Tag>
bool string_compare(unused_type, Char const*, CharEncoding, Tag)
{
return true;
}
}}}}
#endif
@@ -0,0 +1,127 @@
// 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_STRING_GENERATE_FEB_23_2007_1232PM)
#define BOOST_SPIRIT_KARMA_STRING_GENERATE_FEB_23_2007_1232PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <string>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/range/const_iterator.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// pass through character transformation
struct pass_through_filter
{
template <typename Char>
Char operator()(Char ch) const
{
return ch;
}
};
template <typename CharEncoding, typename Tag>
struct encoding_filter
{
template <typename Char>
Char operator()(Char ch) const
{
return spirit::char_class::convert<CharEncoding>::to(Tag(), ch);
}
};
///////////////////////////////////////////////////////////////////////////
// generate a string given by a std::string, applying the given filter
template <typename OutputIterator, typename Char, typename Filter>
inline bool string_generate(OutputIterator& sink, Char const* str
, Filter filter)
{
for (Char ch = *str; ch != 0; ch = *++str)
{
*sink = filter(ch);
++sink;
}
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename Container, typename Filter>
inline bool string_generate(OutputIterator& sink
, Container const& c, Filter filter)
{
typedef typename traits::container_iterator<Container const>::type
iterator;
const iterator end = boost::end(c);
for (iterator it = boost::begin(c); it != end; ++it)
{
*sink = filter(*it);
++sink;
}
return detail::sink_is_good(sink);
}
///////////////////////////////////////////////////////////////////////////
// generate a string without any transformation
template <typename OutputIterator, typename Char>
inline bool string_generate(OutputIterator& sink, Char const* str)
{
return string_generate(sink, str, pass_through_filter());
}
template <typename OutputIterator, typename Container>
inline bool string_generate(OutputIterator& sink
, Container const& c)
{
return string_generate(sink, c, pass_through_filter());
}
///////////////////////////////////////////////////////////////////////////
// generate a string given by a pointer, converting according using a
// given character class and case tag
template <typename OutputIterator, typename Char, typename CharEncoding
, typename Tag>
inline bool string_generate(OutputIterator& sink
, Char const* str
, CharEncoding, Tag)
{
return string_generate(sink, str, encoding_filter<CharEncoding, Tag>());
}
template <typename OutputIterator, typename Container
, typename CharEncoding, typename Tag>
inline bool
string_generate(OutputIterator& sink
, Container const& c
, CharEncoding, Tag)
{
return string_generate(sink, c, encoding_filter<CharEncoding, Tag>());
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Char>
inline bool string_generate(OutputIterator& sink
, Char const* str
, unused_type, unused_type)
{
return string_generate(sink, str);
}
template <typename OutputIterator, typename Container>
inline bool string_generate(OutputIterator& sink
, Container const& c
, unused_type, unused_type)
{
return string_generate(sink, c);
}
}}}}
#endif
@@ -0,0 +1,51 @@
// 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_UNUSED_DELIMITER_MAR_15_2009_0923PM)
#define BOOST_SPIRIT_KARMA_UNUSED_DELIMITER_MAR_15_2009_0923PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Delimiter>
struct unused_delimiter : unused_type
{
unused_delimiter(Delimiter const& delim)
: delimiter(delim) {}
Delimiter const& delimiter;
private:
// silence MSVC warning C4512: assignment operator could not be generated
unused_delimiter& operator= (unused_delimiter const&);
};
// If a surrounding verbatim[] directive was specified, the current
// delimiter is of the type unused_delimiter. In this case we
// re-activate the delimiter which was active before the verbatim[]
// directive.
template <typename Delimiter, typename Default>
inline Delimiter const&
get_delimiter(unused_delimiter<Delimiter> const& u, Default const&)
{
return u.delimiter;
}
// If no surrounding verbatim[] directive was specified we activate
// a single space as the delimiter to use.
template <typename Delimiter, typename Default>
inline Default const&
get_delimiter(Delimiter const&, Default const& d)
{
return d;
}
}}}}
#endif
@@ -0,0 +1,75 @@
// 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_DIRECTIVE_FEB_21_2007_0833PM)
#define BOOST_SPIRIT_KARMA_DIRECTIVE_FEB_21_2007_0833PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/directive/encoding.hpp>
///////////////////////////////////////////////////////////////////////////////
// directives related to alignment
// left_align[...], right_align[...], center[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/left_alignment.hpp>
#include <boost/spirit/home/karma/directive/right_alignment.hpp>
#include <boost/spirit/home/karma/directive/center_alignment.hpp>
///////////////////////////////////////////////////////////////////////////////
// directives related to truncating length
// maxwidth[...], columns[]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/maxwidth.hpp>
#include <boost/spirit/home/karma/directive/columns.hpp>
///////////////////////////////////////////////////////////////////////////////
// directives related to character case
// lower[...] and upper[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/upper_lower_case.hpp>
///////////////////////////////////////////////////////////////////////////////
// directives related to delimiting generators
// delimit[...] and verbatim[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/verbatim.hpp>
#include <boost/spirit/home/karma/directive/delimit.hpp>
#include <boost/spirit/home/karma/directive/no_delimit.hpp>
///////////////////////////////////////////////////////////////////////////////
// repeat directives
// repeat[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/repeat.hpp>
///////////////////////////////////////////////////////////////////////////////
// omit, skip, and duplicate directives
// omit[...], skip[...], duplicate[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/omit.hpp>
#include <boost/spirit/home/karma/directive/duplicate.hpp>
///////////////////////////////////////////////////////////////////////////////
// buffer directive
// buffer[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/buffer.hpp>
///////////////////////////////////////////////////////////////////////////////
// strict and relaxed directives
// strict[...], relaxed[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/strict_relaxed.hpp>
///////////////////////////////////////////////////////////////////////////////
// as_string and as_wstring directives
// as_string[...], as_wstring[...]
///////////////////////////////////////////////////////////////////////////////
#include <boost/spirit/home/karma/directive/as.hpp>
#endif
@@ -0,0 +1,165 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2010 Bryce Lelbach
//
// 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(SPIRIT_KARMA_AS_DEC_18_0510PM)
#define SPIRIT_KARMA_AS_DEC_18_0510PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/as.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
namespace boost { namespace spirit { namespace karma
{
template <typename T>
struct as
: stateful_tag_type<T, tag::as>
{
BOOST_SPIRIT_ASSERT_MSG(
(traits::is_container<T>::type::value),
error_type_must_be_a_container,
(T));
};
}}}
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables as_string[...]
template <>
struct use_directive<karma::domain, tag::as_string>
: mpl::true_ {};
// enables as_wstring[...]
template <>
struct use_directive<karma::domain, tag::as_wstring>
: mpl::true_ {};
// enables as<T>[...]
template <typename T>
struct use_directive<karma::domain, tag::stateful_tag<T, tag::as> >
: mpl::true_
{};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::as_string;
using spirit::as_wstring;
#endif
using spirit::as_string_type;
using spirit::as_wstring_type;
///////////////////////////////////////////////////////////////////////////
// as_directive allows to hook custom conversions to string into the
// output generation process
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T>
struct as_directive
: unary_generator<as_directive<Subject, T> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
as_directive(Subject const& subject)
: subject(subject) {}
template <typename Context, typename Iterator>
struct attribute
{
typedef T type;
};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
if (!traits::valid_as<T>(attr))
return false;
return subject.generate(sink, ctx, d, traits::as<T>(attr)) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
info what(Context& context) const
{
return info("as", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::as_string, Subject, Modifiers>
{
typedef as_directive<Subject, std::string> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
template <typename Subject, typename Modifiers>
struct make_directive<tag::as_wstring, Subject, Modifiers>
{
typedef as_directive<Subject, std::basic_string<wchar_t> > result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
template <typename T, typename Subject, typename Modifiers>
struct make_directive<tag::stateful_tag<T, tag::as>, Subject, Modifiers>
{
typedef as_directive<Subject, T> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T>
struct has_semantic_action<karma::as_directive<Subject, T> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::as_directive<Subject, T>, Attribute
, Context, Iterator>
: mpl::false_ {}; // always dereference attribute if used in sequences
}}}
#endif
@@ -0,0 +1,132 @@
// 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(SPIRIT_KARMA_BUFFER_AUG_03_2009_0949AM)
#define SPIRIT_KARMA_BUFFER_AUG_03_2009_0949AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::buffer> // enables buffer
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::buffer;
#endif
using spirit::buffer_type;
///////////////////////////////////////////////////////////////////////////
// buffer_directive buffers all generated output of the embedded generator
// and flushes it only if the whole embedded generator succeeds
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct buffer_directive : unary_generator<buffer_directive<Subject> >
{
typedef Subject subject_type;
typedef mpl::int_<
subject_type::properties::value |
generator_properties::countingbuffer
> properties;
buffer_directive(Subject const& subject)
: subject(subject) {}
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// wrap the given output iterator to avoid output as long as the
// embedded generator (subject) fails
detail::enable_buffering<OutputIterator> buffering(sink);
bool r = false;
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = subject.generate(sink, ctx, d, attr);
}
if (r)
buffering.buffer_copy();
return r;
}
template <typename Context>
info what(Context& context) const
{
return info("buffer", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::buffer, Subject, Modifiers>
{
typedef buffer_directive<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
// make sure buffer[buffer[...]] does not result in double buffering
template <typename Subject, typename Modifiers>
struct make_directive<tag::buffer, buffer_directive<Subject>, Modifiers>
{
typedef buffer_directive<Subject> result_type;
result_type operator()(unused_type
, buffer_directive<Subject> const& subject, unused_type) const
{
return subject;
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::buffer_directive<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::buffer_directive<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,335 @@
// 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_CENTER_ALIGNMENT_FEB_27_2007_1216PM)
#define BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/default_width.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/integer_traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables center[]
template <>
struct use_directive<karma::domain, tag::center>
: mpl::true_ {};
// enables center(d)[g] and center(w)[g], where d is a generator
// and w is a maximum width
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::center, fusion::vector1<T> > >
: mpl::true_ {};
// enables *lazy* center(d)[g], where d provides a generator
template <>
struct use_lazy_directive<karma::domain, tag::center, 1>
: mpl::true_ {};
// enables center(w, d)[g], where d is a generator and w is a maximum
// width
template <typename Width, typename Padding>
struct use_directive<karma::domain
, terminal_ex<tag::center, fusion::vector2<Width, Padding> > >
: spirit::traits::matches<karma::domain, Padding> {};
// enables *lazy* center(w, d)[g], where d provides a generator and w is
// a maximum width
template <>
struct use_lazy_directive<karma::domain, tag::center, 2>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::center;
#endif
using spirit::center_type;
namespace detail
{
///////////////////////////////////////////////////////////////////////
// The center_generate template function is used for all the
// different flavors of the center[] directive.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Embedded, typename Padding>
inline static bool
center_generate(OutputIterator& sink, Context& ctx,
Delimiter const& d, Attribute const& attr, Embedded const& e,
unsigned int const width, Padding const& p)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
#endif
// wrap the given output iterator to allow left padding
detail::enable_buffering<OutputIterator> buffering(sink, width);
bool r = false;
// first generate the embedded output
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = e.generate(sink, ctx, d, attr);
} // re-enable counting
buffering.disable(); // do not perform buffering any more
// generate the left padding
detail::enable_counting<OutputIterator> counting(sink);
std::size_t const pre = width - (buffering.buffer_size() + width)/2;
while (r && counting.count() < pre)
r = p.generate(sink, ctx, unused, unused);
if (r) {
// copy the embedded output to the target output iterator
buffering.buffer_copy();
// generate the right padding
while (r && counting.count() < width)
r = p.generate(sink, ctx, unused, unused);
}
return r;
}
}
///////////////////////////////////////////////////////////////////////////
// The simple left alignment directive is used for center[...]
// generators. It uses default values for the generated width (defined via
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
// generator (always spaces).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width = detail::default_width>
struct simple_center_alignment
: unary_generator<simple_center_alignment<Subject, Width> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::countingbuffer | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
simple_center_alignment(Subject const& subject, Width width = Width())
: subject(subject), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::center_generate(sink, ctx, d, attr,
subject, width, compile<karma::domain>(' '));
}
template <typename Context>
info what(Context& context) const
{
return info("center", subject.what(context));
}
Subject subject;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// The left alignment directive with padding, is used for generators like
// center(padding)[...], where padding is a arbitrary generator
// expression. It uses a default value for the generated width (defined
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Padding
, typename Width = detail::default_width>
struct padding_center_alignment
: unary_generator<padding_center_alignment<Subject, Padding, Width> >
{
typedef Subject subject_type;
typedef Padding padding_type;
typedef mpl::int_<
generator_properties::countingbuffer |
subject_type::properties::value | padding_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<Subject, Context, Iterator>
{};
padding_center_alignment(Subject const& subject, Padding const& padding
, Width width = Width())
: subject(subject), padding(padding), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::center_generate(sink, ctx, d, attr,
subject, width, padding);
}
template <typename Context>
info what(Context& context) const
{
return info("center", subject.what(context));
}
Subject subject;
Padding padding;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// creates center[] directive generator
template <typename Subject, typename Modifiers>
struct make_directive<tag::center, Subject, Modifiers>
{
typedef simple_center_alignment<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
// creates center(width)[] directive generator
template <typename Width, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::center, fusion::vector1<Width> >
, Subject, Modifiers
, typename enable_if_c< integer_traits<Width>::is_integral >::type>
{
typedef simple_center_alignment<Subject, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
// creates center(pad)[] directive generator
template <typename Padding, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::center, fusion::vector1<Padding> >
, Subject, Modifiers
, typename enable_if<
mpl::and_<
spirit::traits::matches<karma::domain, Padding>,
mpl::not_<mpl::bool_<integer_traits<Padding>::is_integral> >
>
>::type>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_center_alignment<Subject, padding_type> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<0>(term.args), modifiers));
}
};
// creates center(width, pad)[] directive generator
template <typename Width, typename Padding, typename Subject
, typename Modifiers>
struct make_directive<
terminal_ex<tag::center, fusion::vector2<Width, Padding> >
, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_center_alignment<Subject, padding_type, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<1>(term.args), modifiers)
, fusion::at_c<0>(term.args));
}
};
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width>
struct has_semantic_action<karma::simple_center_alignment<Subject, Width> >
: unary_has_semantic_action<Subject> {};
template <typename Subject, typename Padding, typename Width>
struct has_semantic_action<
karma::padding_center_alignment<Subject, Padding, Width> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::simple_center_alignment<Subject, Width>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
template <typename Subject, typename Padding, typename Width
, typename Attribute, typename Context, typename Iterator>
struct handles_container<
karma::padding_center_alignment<Subject, Padding, Width>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,293 @@
// 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_COLUMNS_DEC_03_2009_0736AM)
#define BOOST_SPIRIT_KARMA_COLUMNS_DEC_03_2009_0736AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/detail/default_width.hpp>
#include <boost/spirit/home/karma/auxiliary/eol.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/integer_traits.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::columns> // enables columns[]
: mpl::true_ {};
// enables columns(c)[g], where c provides the number of require columns
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::columns, fusion::vector1<T> > >
: mpl::true_ {};
// enables *lazy* columns(c)[g]
template <>
struct use_lazy_directive<karma::domain, tag::columns, 1>
: mpl::true_ {};
// enables columns(c, d)[g], where c provides the number of require columns
// and d is the custom column-delimiter (default is karma::endl)
template <typename T1, typename T2>
struct use_directive<karma::domain
, terminal_ex<tag::columns, fusion::vector2<T1, T2> > >
: boost::spirit::traits::matches<karma::domain, T2> {};
// enables *lazy* columns(c, d)[g]
template <>
struct use_lazy_directive<karma::domain, tag::columns, 2>
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::columns;
#endif
using spirit::columns_type;
namespace detail
{
template <typename Delimiter, typename ColumnDelimiter>
struct columns_delimiter
{
columns_delimiter(Delimiter const& delim
, ColumnDelimiter const& cdelim, unsigned int const numcols)
: delimiter(delim), column_delimiter(cdelim)
, numcolumns(numcols), count(0) {}
template <typename OutputIterator, typename Context
, typename Delimiter_, typename Attribute>
bool generate(OutputIterator& sink, Context&, Delimiter_ const&
, Attribute const&) const
{
// first invoke the embedded delimiter
if (!karma::delimit_out(sink, delimiter))
return false;
// now we count the number of invocations and emit the column
// delimiter if needed
if ((++count % numcolumns) == 0)
return karma::delimit_out(sink, column_delimiter);
return true;
}
// generate a final column delimiter if the last invocation didn't
// emit one
template <typename OutputIterator>
bool delimit_out(OutputIterator& sink) const
{
if (count % numcolumns)
return karma::delimit_out(sink, column_delimiter);
return true;
}
Delimiter const& delimiter;
ColumnDelimiter const& column_delimiter;
unsigned int const numcolumns;
mutable unsigned int count;
private:
// silence MSVC warning C4512: assignment operator could not be generated
columns_delimiter& operator= (columns_delimiter const&);
};
}
///////////////////////////////////////////////////////////////////////////
// The columns_generator is used for columns(c, d)[...] directives.
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename NumColumns, typename ColumnsDelimiter>
struct columns_generator
: unary_generator<columns_generator<Subject, NumColumns, ColumnsDelimiter> >
{
typedef Subject subject_type;
typedef ColumnsDelimiter delimiter_type;
typedef mpl::int_<
subject_type::properties::value | delimiter_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
columns_generator(Subject const& subject, NumColumns const& cols
, ColumnsDelimiter const& cdelimiter)
: subject(subject), numcolumns(cols), column_delimiter(cdelimiter)
{
// having zero number of columns doesn't make any sense
BOOST_ASSERT(numcolumns > 0);
}
template <typename OutputIterator, typename Context
, typename Delimiter, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& delimiter, Attribute const& attr) const
{
// The columns generator dispatches to the embedded generator
// while supplying a new delimiter to use, wrapping the outer
// delimiter.
typedef detail::columns_delimiter<
Delimiter, ColumnsDelimiter
> columns_delimiter_type;
columns_delimiter_type d(delimiter, column_delimiter, numcolumns);
return subject.generate(sink, ctx, d, attr) && d.delimit_out(sink);
}
template <typename Context>
info what(Context& context) const
{
return info("columns", subject.what(context));
}
Subject subject;
NumColumns numcolumns;
ColumnsDelimiter column_delimiter;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// creates columns[] directive
template <typename Subject, typename Modifiers>
struct make_directive<tag::columns, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, eol_type, Modifiers>::type
columns_delimiter_type;
typedef columns_generator<
Subject, detail::default_columns, columns_delimiter_type>
result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
#if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
eol_type const eol = eol_type();
#endif
return result_type(subject, detail::default_columns()
, compile<karma::domain>(eol));
}
};
// creates columns(c)[] directive generator (c is the number of columns)
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::columns, fusion::vector1<T> >
, Subject, Modifiers
, typename enable_if_c<integer_traits<T>::is_integral>::type>
{
typedef typename
result_of::compile<karma::domain, eol_type, Modifiers>::type
columns_delimiter_type;
typedef columns_generator<
Subject, T, columns_delimiter_type
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
#if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
eol_type const eol = eol_type();
#endif
return result_type(subject, fusion::at_c<0>(term.args)
, compile<karma::domain>(eol));
}
};
// creates columns(d)[] directive generator (d is the column delimiter)
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::columns, fusion::vector1<T> >
, Subject, Modifiers
, typename enable_if<
mpl::and_<
spirit::traits::matches<karma::domain, T>,
mpl::not_<mpl::bool_<integer_traits<T>::is_integral> >
>
>::type>
{
typedef typename
result_of::compile<karma::domain, T, Modifiers>::type
columns_delimiter_type;
typedef columns_generator<
Subject, detail::default_columns, columns_delimiter_type
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, detail::default_columns()
, compile<karma::domain>(fusion::at_c<0>(term.args)));
}
};
// creates columns(c, d)[] directive generator (c is the number of columns
// and d is the column delimiter)
template <typename T1, typename T2, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::columns, fusion::vector2<T1, T2> >
, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, T2, Modifiers>::type
columns_delimiter_type;
typedef columns_generator<
Subject, T1, columns_delimiter_type
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type (subject, fusion::at_c<0>(term.args)
, compile<karma::domain>(fusion::at_c<1>(term.args)));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T1, typename T2>
struct has_semantic_action<karma::columns_generator<Subject, T1, T2> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename T1, typename T2, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::columns_generator<Subject, T1, T2>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,200 @@
// 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_DELIMIT_MAR_02_2007_0217PM)
#define BOOST_SPIRIT_KARMA_DELIMIT_MAR_02_2007_0217PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/unused_delimiter.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::delimit> // enables delimit[]
: mpl::true_ {};
// enables delimit(d)[g], where d is a generator
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::delimit, fusion::vector1<T> > >
: boost::spirit::traits::matches<karma::domain, T> {};
// enables *lazy* delimit(d)[g]
template <>
struct use_lazy_directive<karma::domain, tag::delimit, 1>
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::delimit;
#endif
using spirit::delimit_type;
///////////////////////////////////////////////////////////////////////////
// The redelimit_generator generator is used for delimit[...] directives.
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct redelimit_generator : unary_generator<redelimit_generator<Subject> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
redelimit_generator(Subject const& subject)
: subject(subject) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// The delimit_space generator simply dispatches to the embedded
// generator while supplying either the delimiter which has been
// used before a surrounding verbatim[] directive or a single
// space as the new delimiter to use (if no surrounding verbatim[]
// was specified).
return subject.generate(sink, ctx
, detail::get_delimiter(d, compile<karma::domain>(' ')), attr);
}
template <typename Context>
info what(Context& context) const
{
return info("delimit", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// The delimit_generator is used for delimit(d)[...] directives.
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Delimiter>
struct delimit_generator
: unary_generator<delimit_generator<Subject, Delimiter> >
{
typedef Subject subject_type;
typedef Delimiter delimiter_type;
typedef typename subject_type::properties properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
delimit_generator(Subject const& subject, Delimiter const& delimiter)
: subject(subject), delimiter(delimiter) {}
template <typename OutputIterator, typename Context
, typename Delimiter_, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter_ const&
, Attribute const& attr) const
{
// the delimit generator simply dispatches to the embedded
// generator while supplying it's argument as the new delimiter
// to use
return subject.generate(sink, ctx, delimiter, attr);
}
template <typename Context>
info what(Context& context) const
{
return info("delimit", subject.what(context));
}
Subject subject;
Delimiter delimiter;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::delimit, Subject, Modifiers>
{
typedef redelimit_generator<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
template <typename Delimiter, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::delimit, fusion::vector1<Delimiter> >
, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, Delimiter, Modifiers>::type
delimiter_type;
typedef delimit_generator<Subject, delimiter_type> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<0>(term.args)));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::redelimit_generator<Subject> >
: unary_has_semantic_action<Subject> {};
template <typename Subject, typename Delimiter>
struct has_semantic_action<karma::delimit_generator<Subject, Delimiter> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::redelimit_generator<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
template <typename Subject, typename Delimiter, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::delimit_generator<Subject, Delimiter>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,230 @@
// 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(SPIRIT_KARMA_DUPLICATE_JUL_11_2010_0954AM)
#define SPIRIT_KARMA_DUPLICATE_JUL_11_2010_0954AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/fusion/include/cons.hpp>
#include <boost/fusion/include/make_cons.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::duplicate> // enables duplicate
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::duplicate;
#endif
using spirit::duplicate_type;
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
template <typename T
, bool IsSequence = fusion::traits::is_sequence<T>::value>
struct attribute_count
: fusion::result_of::size<T>
{};
template <>
struct attribute_count<unused_type, false>
: mpl::int_<0>
{};
template <typename T>
struct attribute_count<T, false>
: mpl::int_<1>
{};
///////////////////////////////////////////////////////////////////////
template <typename T
, bool IsSequence = fusion::traits::is_sequence<T>::value>
struct first_attribute_of_subject
: remove_reference<typename fusion::result_of::at_c<T, 0>::type>
{};
template <typename T>
struct first_attribute_of_subject<T, false>
: mpl::identity<T>
{};
template <typename T, typename Context, typename Iterator>
struct first_attribute_of
: first_attribute_of_subject<
typename traits::attribute_of<T, Context, Iterator>::type>
{};
///////////////////////////////////////////////////////////////////////
template <typename Attribute, typename T, int N>
struct duplicate_sequence_attribute
{
typedef typename fusion::result_of::make_cons<
reference_wrapper<T const>
, typename duplicate_sequence_attribute<Attribute, T, N-1>::type
>::type type;
static type call(T const& t)
{
return fusion::make_cons(boost::cref(t)
, duplicate_sequence_attribute<Attribute, T, N-1>::call(t));
}
};
template <typename Attribute, typename T>
struct duplicate_sequence_attribute<Attribute, T, 1>
{
typedef typename fusion::result_of::make_cons<
reference_wrapper<T const> >::type type;
static type call(T const& t)
{
return fusion::make_cons(boost::cref(t));
}
};
///////////////////////////////////////////////////////////////////////
template <typename Attribute, typename T
, int N = attribute_count<Attribute>::value
, bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
struct duplicate_attribute
{
BOOST_SPIRIT_ASSERT_MSG(N > 0, invalid_duplication_count, (Attribute));
typedef typename duplicate_sequence_attribute<Attribute, T, N>::type
cons_type;
typedef typename fusion::result_of::as_vector<cons_type>::type type;
static type call(T const& t)
{
return fusion::as_vector(
duplicate_sequence_attribute<Attribute, T, N>::call(t));
}
};
template <typename Attribute, typename T>
struct duplicate_attribute<Attribute, T, 0, false>
{
typedef unused_type type;
static type call(T const&)
{
return unused;
}
};
template <typename Attribute, typename T, int N>
struct duplicate_attribute<Attribute, T, N, false>
{
typedef Attribute const& type;
static type call(T const& t)
{
return t;
}
};
}
template <typename Attribute, typename T>
inline typename detail::duplicate_attribute<Attribute, T>::type
duplicate_attribute(T const& t)
{
return detail::duplicate_attribute<Attribute, T>::call(t);
}
///////////////////////////////////////////////////////////////////////////
// duplicate_directive duplicate its attribute for all elements of the
// subject generator without generating anything itself
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct duplicate_directive : unary_generator<duplicate_directive<Subject> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
duplicate_directive(Subject const& subject)
: subject(subject) {}
template <typename Context, typename Iterator = unused_type>
struct attribute
: detail::first_attribute_of<Subject, Context, Iterator>
{};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
typedef typename traits::attribute_of<Subject, Context>::type
subject_attr_type;
return subject.generate(sink, ctx, d
, duplicate_attribute<subject_attr_type>(attr));
}
template <typename Context>
info what(Context& context) const
{
return info("duplicate", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::duplicate, Subject, Modifiers>
{
typedef duplicate_directive<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::duplicate_directive<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::duplicate_directive<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,35 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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(SPIRIT_KARMA_ENCODING_MARCH_05_2010_0550PM)
#define SPIRIT_KARMA_ENCODING_MARCH_05_2010_0550PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables encoding
template <typename CharEncoding>
struct use_directive<
karma::domain, tag::char_code<tag::encoding, CharEncoding> >
: mpl::true_ {};
template <typename CharEncoding>
struct is_modifier_directive<
karma::domain, tag::char_code<tag::encoding, CharEncoding> >
: mpl::true_ {};
}}
#endif
@@ -0,0 +1,318 @@
// 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_LEFT_ALIGNMENT_FEB_27_2007_1216PM)
#define BOOST_SPIRIT_KARMA_LEFT_ALIGNMENT_FEB_27_2007_1216PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/default_width.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/integer_traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables left_align[]
template <>
struct use_directive<karma::domain, tag::left_align>
: mpl::true_ {};
// enables left_align(d)[g] and left_align(w)[g], where d is a generator
// and w is a maximum width
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::left_align, fusion::vector1<T> > >
: mpl::true_ {};
// enables *lazy* left_align(d)[g], where d provides a generator
template <>
struct use_lazy_directive<karma::domain, tag::left_align, 1>
: mpl::true_ {};
// enables left_align(w, d)[g], where d is a generator and w is a maximum
// width
template <typename Width, typename Padding>
struct use_directive<karma::domain
, terminal_ex<tag::left_align, fusion::vector2<Width, Padding> > >
: spirit::traits::matches<karma::domain, Padding> {};
// enables *lazy* left_align(w, d)[g], where d provides a generator and w
// is a maximum width
template <>
struct use_lazy_directive<karma::domain, tag::left_align, 2>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::left_align;
#endif
using spirit::left_align_type;
namespace detail
{
///////////////////////////////////////////////////////////////////////
// The left_align_generate template function is used for all the
// different flavors of the left_align[] directive.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Embedded, typename Padding>
inline static bool
left_align_generate(OutputIterator& sink, Context& ctx,
Delimiter const& d, Attribute const& attr, Embedded const& e,
unsigned int const width, Padding const& p)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
#endif
// wrap the given output iterator to allow counting
detail::enable_counting<OutputIterator> counting(sink);
// first generate the underlying output
bool r = e.generate(sink, ctx, d, attr);
// pad the output until the max width is reached
while(r && counting.count() < width)
r = p.generate(sink, ctx, unused, unused);
return r;
}
}
///////////////////////////////////////////////////////////////////////////
// The simple left alignment directive is used for left_align[...]
// generators. It uses default values for the generated width (defined via
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
// generator (always spaces).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width = detail::default_width>
struct simple_left_alignment
: unary_generator<simple_left_alignment<Subject, Width> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::counting | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
simple_left_alignment(Subject const& subject, Width width = Width())
: subject(subject), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::left_align_generate(sink, ctx, d, attr,
subject, width, compile<karma::domain>(' '));
}
template <typename Context>
info what(Context& context) const
{
return info("left_align", subject.what(context));
}
Subject subject;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// The left alignment directive with padding, is used for generators like
// left_align(padding)[...], where padding is a arbitrary generator
// expression. It uses a default value for the generated width (defined
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Padding
, typename Width = detail::default_width>
struct padding_left_alignment
: unary_generator<padding_left_alignment<Subject, Padding, Width> >
{
typedef Subject subject_type;
typedef Padding padding_type;
typedef mpl::int_<
generator_properties::counting |
subject_type::properties::value | padding_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
padding_left_alignment(Subject const& subject, Padding const& padding
, Width width = Width())
: subject(subject), padding(padding), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::left_align_generate(sink, ctx, d, attr,
subject, width, padding);
}
template <typename Context>
info what(Context& context) const
{
return info("left_align", subject.what(context));
}
Subject subject;
Padding padding;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// creates left_align[] directive generator
template <typename Subject, typename Modifiers>
struct make_directive<tag::left_align, Subject, Modifiers>
{
typedef simple_left_alignment<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
// creates left_align(width)[] directive generator
template <typename Width, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::left_align, fusion::vector1<Width> >
, Subject, Modifiers
, typename enable_if_c< integer_traits<Width>::is_integral >::type>
{
typedef simple_left_alignment<Subject, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
// creates left_align(pad)[] directive generator
template <typename Padding, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::left_align, fusion::vector1<Padding> >
, Subject, Modifiers
, typename enable_if<
mpl::and_<
spirit::traits::matches<karma::domain, Padding>,
mpl::not_<mpl::bool_<integer_traits<Padding>::is_integral> >
>
>::type>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_left_alignment<Subject, padding_type> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<0>(term.args), modifiers));
}
};
// creates left_align(width, pad)[] directive generator
template <typename Width, typename Padding, typename Subject
, typename Modifiers>
struct make_directive<
terminal_ex<tag::left_align, fusion::vector2<Width, Padding> >
, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_left_alignment<Subject, padding_type, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<1>(term.args), modifiers)
, fusion::at_c<0>(term.args));
}
};
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width>
struct has_semantic_action<karma::simple_left_alignment<Subject, Width> >
: unary_has_semantic_action<Subject> {};
template <typename Subject, typename Padding, typename Width>
struct has_semantic_action<
karma::padding_left_alignment<Subject, Padding, Width> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::simple_left_alignment<Subject, Width>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
template <typename Subject, typename Padding, typename Width
, typename Attribute, typename Context, typename Iterator>
struct handles_container<
karma::padding_left_alignment<Subject, Padding, Width>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,246 @@
// 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_MAXWIDTH_MAR_18_2009_0827AM)
#define BOOST_SPIRIT_KARMA_MAXWIDTH_MAR_18_2009_0827AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/default_width.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables maxwidth[]
template <>
struct use_directive<karma::domain, tag::maxwidth>
: mpl::true_ {};
// enables maxwidth(w)[g], where w provides a maxwidth
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::maxwidth, fusion::vector1<T> > >
: mpl::true_ {};
// enables *lazy* maxwidth(w)[g], where w provides a maxwidth
template <>
struct use_lazy_directive<karma::domain, tag::maxwidth, 1>
: mpl::true_ {};
// enables maxwidth(w, r)[g], where w provides a maxwidth and r is an output
// iterator used to receive the rest of the output not fitting into the
// maxwidth limit
template <typename T, typename RestIter>
struct use_directive<karma::domain
, terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > >
: mpl::true_ {};
// enables *lazy* maxwidth(w, r)[g], where w provides a maxwidth and r is
// an output iterator used to receive the rest of the output not fitting
// into the maxwidth limit
template <>
struct use_lazy_directive<karma::domain, tag::maxwidth, 2>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::maxwidth;
#endif
using spirit::maxwidth_type;
namespace detail
{
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename RestIterator>
bool buffer_copy_rest(detail::enable_buffering<OutputIterator>& buff
, std::size_t start_at, RestIterator& dest)
{
return buff.buffer_copy_rest(dest, start_at);
}
template <typename OutputIterator>
bool buffer_copy_rest(detail::enable_buffering<OutputIterator>&
, std::size_t, unused_type)
{
return true;
}
///////////////////////////////////////////////////////////////////////
// The maxwidth_generate template function is used for all the
// different flavors of the maxwidth[] directive.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Embedded, typename Rest>
inline static bool
maxwidth_generate(OutputIterator& sink, Context& ctx,
Delimiter const& d, Attribute const& attr, Embedded const& e,
unsigned int const maxwidth, Rest& restdest)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
#endif
// wrap the given output iterator to allow buffering, but disable
// counting
detail::enable_buffering<OutputIterator> buffering(sink);
// generate the underlying output and copy the embedded
// output to the target output iterator applying the given
// maxwidth
bool r = false;
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = e.generate(sink, ctx, d, attr);
} // re-enable counting
return r && buffering.buffer_copy(maxwidth) &&
buffer_copy_rest(buffering, maxwidth, restdest);
}
}
///////////////////////////////////////////////////////////////////////////
// The maxwidth directive is used for maxwidth[...]
// generators. It uses default values for the generated width (defined via
// the BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH constant).
//
// The maxwidth with width directive, is used for generators
// like maxwidth(width)[...].
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width = detail::default_max_width
, typename Rest = unused_type>
struct maxwidth_width
: unary_generator<maxwidth_width<Subject, Width, Rest> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::countingbuffer | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
maxwidth_width(Subject const& subject, Width const& w = Width()
, Rest const& r = Rest())
: subject(subject), width(w), rest(r) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::maxwidth_generate(sink, ctx, d, attr, subject
, width, rest);
}
template <typename Context>
info what(Context& context) const
{
return info("maxwidth", subject.what(context));
}
Subject subject;
Width width;
Rest rest;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// creates maxwidth[] directive generator
template <typename Subject, typename Modifiers>
struct make_directive<tag::maxwidth, Subject, Modifiers>
{
typedef maxwidth_width<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
// creates maxwidth(width)[] directive generator
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::maxwidth, fusion::vector1<T> >
, Subject, Modifiers>
{
typedef maxwidth_width<Subject, T> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args), unused);
}
};
// creates maxwidth(width, restiter)[] directive generator
template <
typename T, typename RestIter, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> >
, Subject, Modifiers>
{
typedef maxwidth_width<Subject, T, RestIter> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args));
}
};
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width, typename Rest>
struct has_semantic_action<karma::maxwidth_width<Subject, Width, Rest> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::maxwidth_width<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,116 @@
// 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_NO_DELIMIT_JAN_19_2010_0920AM)
#define BOOST_SPIRIT_KARMA_NO_DELIMIT_JAN_19_2010_0920AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/unused_delimiter.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::no_delimit> // enables no_delimit[]
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::no_delimit;
#endif
using spirit::no_delimit_type;
///////////////////////////////////////////////////////////////////////////
// The no_delimit generator is used for no_delimit[...] directives.
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct no_delimit_generator
: unary_generator<no_delimit_generator<Subject> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
no_delimit_generator(Subject const& subject)
: subject(subject) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// the no_delimit generator simply dispatches to the embedded
// generator while supplying unused_delimiter as the new delimiter
// to avoid delimiting down the generator stream
typedef detail::unused_delimiter<Delimiter> unused_delimiter;
// the difference to verbatim[] is that this does not post-delimit
return subject.generate(sink, ctx, unused_delimiter(d), attr);
}
template <typename Context>
info what(Context& context) const
{
return info("no_delimit", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::no_delimit, Subject, Modifiers>
{
typedef no_delimit_generator<Subject> result_type;
result_type
operator()(unused_type, Subject const& subject, unused_type) const
{
return result_type(subject);
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::no_delimit_generator<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::no_delimit_generator<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,135 @@
// 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(SPIRIT_KARMA_OMIT_JUL_20_2009_1008AM)
#define SPIRIT_KARMA_OMIT_JUL_20_2009_1008AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::omit> // enables omit
: mpl::true_ {};
template <>
struct use_directive<karma::domain, tag::skip> // enables skip
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::omit;
using spirit::skip;
#endif
using spirit::omit_type;
using spirit::skip_type;
///////////////////////////////////////////////////////////////////////////
// omit_directive consumes the attribute of subject generator without
// generating anything
///////////////////////////////////////////////////////////////////////////
template <typename Subject, bool Execute>
struct omit_directive : unary_generator<omit_directive<Subject, Execute> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::disabling | subject_type::properties::value
> properties;
omit_directive(Subject const& subject)
: subject(subject) {}
template <typename Context, typename Iterator = unused_type>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// We need to actually compile the output operation as we don't
// have any other means to verify, whether the passed attribute is
// compatible with the subject.
// omit[] will execute the code, while skip[] doesn't execute it
if (Execute) {
// wrap the given output iterator to avoid output
detail::disable_output<OutputIterator> disable(sink);
return subject.generate(sink, ctx, d, attr);
}
return true;
}
template <typename Context>
info what(Context& context) const
{
return info(Execute ? "omit" : "skip", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::omit, Subject, Modifiers>
{
typedef omit_directive<Subject, true> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
template <typename Subject, typename Modifiers>
struct make_directive<tag::skip, Subject, Modifiers>
{
typedef omit_directive<Subject, false> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, bool Execute>
struct has_semantic_action<karma::omit_directive<Subject, Execute> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, bool Execute, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::omit_directive<Subject, Execute>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,397 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_REPEAT_MAY_18_2009_0926AM)
#define SPIRIT_KARMA_REPEAT_MAY_18_2009_0926AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/operator/kleene.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/fusion/include/at.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::repeat> // enables repeat[p]
: mpl::true_ {};
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::repeat // enables repeat(exact)[p]
, fusion::vector1<T> >
> : mpl::true_ {};
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::repeat // enables repeat(min, max)[p]
, fusion::vector2<T, T> >
> : mpl::true_ {};
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::repeat // enables repeat(min, inf)[p]
, fusion::vector2<T, inf_type> >
> : mpl::true_ {};
template <> // enables *lazy* repeat(exact)[p]
struct use_lazy_directive<
karma::domain
, tag::repeat
, 1 // arity
> : mpl::true_ {};
template <> // enables *lazy* repeat(min, max)[p]
struct use_lazy_directive< // and repeat(min, inf)[p]
karma::domain
, tag::repeat
, 2 // arity
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::repeat;
using spirit::inf;
#endif
using spirit::repeat_type;
using spirit::inf_type;
///////////////////////////////////////////////////////////////////////////
// handles repeat(exact)[p]
template <typename T>
struct exact_iterator
{
exact_iterator(T const exact)
: exact(exact) {}
typedef T type;
T start() const { return 0; }
bool got_max(T i) const { return i >= exact; }
bool got_min(T i) const { return i >= exact; }
T const exact;
private:
// silence MSVC warning C4512: assignment operator could not be generated
exact_iterator& operator= (exact_iterator const&);
};
// handles repeat(min, max)[p]
template <typename T>
struct finite_iterator
{
finite_iterator(T const min, T const max)
: min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
, max BOOST_PREVENT_MACRO_SUBSTITUTION (max) {}
typedef T type;
T start() const { return 0; }
bool got_max(T i) const { return i >= max; }
bool got_min(T i) const { return i >= min; }
T const min;
T const max;
private:
// silence MSVC warning C4512: assignment operator could not be generated
finite_iterator& operator= (finite_iterator const&);
};
// handles repeat(min, inf)[p]
template <typename T>
struct infinite_iterator
{
infinite_iterator(T const min)
: min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
typedef T type;
T start() const { return 0; }
bool got_max(T /*i*/) const { return false; }
bool got_min(T i) const { return i >= min; }
T const min;
private:
// silence MSVC warning C4512: assignment operator could not be generated
infinite_iterator& operator= (infinite_iterator const&);
};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename LoopIter, typename Strict
, typename Derived>
struct base_repeat_generator : unary_generator<Derived>
{
private:
// iterate over the given container until its exhausted or the embedded
// generator succeeds
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, mpl::false_) const
{
// Failing subject generators are just skipped. This allows to
// selectively generate items in the provided attribute.
while (!f.is_at_end())
{
bool r = !f(subject);
if (r)
return true;
if (!f.is_at_end())
f.next();
}
return false;
}
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, mpl::true_) const
{
return !f(subject);
}
// There is no way to distinguish a failed generator from a
// generator to be skipped. We assume the user takes responsibility
// for ending the loop if no attribute is specified.
template <typename F>
bool generate_subject(F f, unused_type, mpl::false_) const
{
return !f(subject);
}
public:
typedef Subject subject_type;
typedef mpl::int_<subject_type::properties::value> properties;
// Build a std::vector from the subject's attribute. Note
// that build_std_vector may return unused_type if the
// subject's attribute is an unused_type.
template <typename Context, typename Iterator>
struct attribute
: traits::build_std_vector<
typename traits::attribute_of<Subject, Context, Iterator>::type
>
{};
base_repeat_generator(Subject const& subject, LoopIter const& iter)
: subject(subject), iter(iter) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
typedef detail::fail_function<
OutputIterator, Context, Delimiter
> fail_function;
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
typedef
typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
fail_function, Attribute, indirect_iterator_type, mpl::false_>
pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(it), indirect_iterator_type(end));
// generate the minimal required amount of output
typename LoopIter::type i = iter.start();
for (/**/; !pass.is_at_end() && !iter.got_min(i); ++i)
{
if (!generate_subject(pass, attr, Strict()))
{
// if we fail before reaching the minimum iteration
// required, do not output anything and return false
return false;
}
}
if (pass.is_at_end() && !iter.got_min(i))
return false; // insufficient attribute elements
// generate some more up to the maximum specified
for (/**/; !pass.is_at_end() && !iter.got_max(i); ++i)
{
if (!generate_subject(pass, attr, Strict()))
break;
}
return detail::sink_is_good(sink);
}
template <typename Context>
info what(Context& context) const
{
return info("repeat", subject.what(context));
}
Subject subject;
LoopIter iter;
};
template <typename Subject, typename LoopIter>
struct repeat_generator
: base_repeat_generator<
Subject, LoopIter, mpl::false_
, repeat_generator<Subject, LoopIter> >
{
typedef base_repeat_generator<
Subject, LoopIter, mpl::false_, repeat_generator
> base_repeat_generator_;
repeat_generator(Subject const& subject, LoopIter const& iter)
: base_repeat_generator_(subject, iter) {}
};
template <typename Subject, typename LoopIter>
struct strict_repeat_generator
: base_repeat_generator<
Subject, LoopIter, mpl::true_
, strict_repeat_generator<Subject, LoopIter> >
{
typedef base_repeat_generator<
Subject, LoopIter, mpl::true_, strict_repeat_generator
> base_repeat_generator_;
strict_repeat_generator(Subject const& subject, LoopIter const& iter)
: base_repeat_generator_(subject, iter) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::repeat, Subject, Modifiers>
{
typedef typename mpl::if_<
detail::get_stricttag<Modifiers>
, strict_kleene<Subject>, kleene<Subject>
>::type result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
{
typedef exact_iterator<T> iterator_type;
typedef typename mpl::if_<
detail::get_stricttag<Modifiers>
, strict_repeat_generator<Subject, iterator_type>
, repeat_generator<Subject, iterator_type>
>::type result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
{
typedef finite_iterator<T> iterator_type;
typedef typename mpl::if_<
detail::get_stricttag<Modifiers>
, strict_repeat_generator<Subject, iterator_type>
, repeat_generator<Subject, iterator_type>
>::type result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
return result_type(subject,
iterator_type(
fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args)
)
);
}
};
template <typename T, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::repeat
, fusion::vector2<T, inf_type> >, Subject, Modifiers>
{
typedef infinite_iterator<T> iterator_type;
typedef typename mpl::if_<
detail::get_stricttag<Modifiers>
, strict_repeat_generator<Subject, iterator_type>
, repeat_generator<Subject, iterator_type>
>::type result_type;
template <typename Terminal>
result_type operator()(
Terminal const& term, Subject const& subject, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename LoopIter>
struct has_semantic_action<karma::repeat_generator<Subject, LoopIter> >
: unary_has_semantic_action<Subject> {};
template <typename Subject, typename LoopIter>
struct has_semantic_action<karma::strict_repeat_generator<Subject, LoopIter> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename LoopIter, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::repeat_generator<Subject, LoopIter>, Attribute
, Context, Iterator>
: mpl::true_ {};
template <typename Subject, typename LoopIter, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::strict_repeat_generator<Subject, LoopIter>, Attribute
, Context, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,327 @@
// 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_RIGHT_ALIGNMENT_FEB_27_2007_1216PM)
#define BOOST_SPIRIT_KARMA_RIGHT_ALIGNMENT_FEB_27_2007_1216PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/default_width.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/integer_traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables right_align[]
template <>
struct use_directive<karma::domain, tag::right_align>
: mpl::true_ {};
// enables right_align(d)[g] and right_align(w)[g], where d is a generator
// and w is a maximum width
template <typename T>
struct use_directive<karma::domain
, terminal_ex<tag::right_align, fusion::vector1<T> > >
: mpl::true_ {};
// enables *lazy* right_align(d)[g], where d provides a generator
template <>
struct use_lazy_directive<karma::domain, tag::right_align, 1>
: mpl::true_ {};
// enables right_align(w, d)[g], where d is a generator and w is a maximum
// width
template <typename Width, typename Padding>
struct use_directive<karma::domain
, terminal_ex<tag::right_align, fusion::vector2<Width, Padding> > >
: spirit::traits::matches<karma::domain, Padding> {};
// enables *lazy* right_align(w, d)[g], where d provides a generator and w
// is a maximum width
template <>
struct use_lazy_directive<karma::domain, tag::right_align, 2>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::right_align;
#endif
using spirit::right_align_type;
namespace detail
{
///////////////////////////////////////////////////////////////////////
// The right_align_generate template function is used for all the
// different flavors of the right_align[] directive.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Embedded, typename Padding>
inline static bool
right_align_generate(OutputIterator& sink, Context& ctx,
Delimiter const& d, Attribute const& attr, Embedded const& e,
unsigned int const width, Padding const& p)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
#endif
// wrap the given output iterator to allow left padding
detail::enable_buffering<OutputIterator> buffering(sink, width);
bool r = false;
// first generate the embedded output
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = e.generate(sink, ctx, d, attr);
} // re-enable counting
buffering.disable(); // do not perform buffering any more
// generate the left padding
detail::enable_counting<OutputIterator> counting(sink, buffering.buffer_size());
while(r && counting.count() < width)
r = p.generate(sink, ctx, unused, unused);
// copy the buffered output to the target output iterator
if (r)
buffering.buffer_copy();
return r;
}
}
///////////////////////////////////////////////////////////////////////////
// The simple left alignment directive is used for right_align[...]
// generators. It uses default values for the generated width (defined via
// the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
// generator (always spaces).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width = detail::default_width>
struct simple_right_alignment
: unary_generator<simple_right_alignment<Subject, Width> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::countingbuffer | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
simple_right_alignment(Subject const& subject, Width width = Width())
: subject(subject), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::right_align_generate(sink, ctx, d, attr,
subject, width, compile<karma::domain>(' '));
}
template <typename Context>
info what(Context& context) const
{
return info("right_align", subject.what(context));
}
Subject subject;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// The left alignment directive with padding, is used for generators like
// right_align(padding)[...], where padding is a arbitrary generator
// expression. It uses a default value for the generated width (defined
// via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Padding
, typename Width = detail::default_width>
struct padding_right_alignment
: unary_generator<padding_right_alignment<Subject, Padding, Width> >
{
typedef Subject subject_type;
typedef Padding padding_type;
typedef mpl::int_<
generator_properties::countingbuffer |
subject_type::properties::value | padding_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
padding_right_alignment(Subject const& subject, Padding const& padding
, Width width = Width())
: subject(subject), padding(padding), width(width) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
return detail::right_align_generate(sink, ctx, d, attr,
subject, width, padding);
}
template <typename Context>
info what(Context& context) const
{
return info("right_align", subject.what(context));
}
Subject subject;
Padding padding;
Width width;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
// creates right_align[] directive generator
template <typename Subject, typename Modifiers>
struct make_directive<tag::right_align, Subject, Modifiers>
{
typedef simple_right_alignment<Subject> result_type;
result_type operator()(unused_type, Subject const& subject
, unused_type) const
{
return result_type(subject);
}
};
// creates right_align(width)[] directive generator
template <typename Width, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::right_align, fusion::vector1<Width> >
, Subject, Modifiers
, typename enable_if_c< integer_traits<Width>::is_integral >::type>
{
typedef simple_right_alignment<Subject, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
// creates right_align(pad)[] directive generator
template <typename Padding, typename Subject, typename Modifiers>
struct make_directive<
terminal_ex<tag::right_align, fusion::vector1<Padding> >
, Subject, Modifiers
, typename enable_if<
mpl::and_<
spirit::traits::matches<karma::domain, Padding>,
mpl::not_<mpl::bool_<integer_traits<Padding>::is_integral> >
>
>::type>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_right_alignment<Subject, padding_type> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<0>(term.args), modifiers));
}
};
// creates right_align(width, pad)[] directive generator
template <typename Width, typename Padding, typename Subject
, typename Modifiers>
struct make_directive<
terminal_ex<tag::right_align, fusion::vector2<Width, Padding> >
, Subject, Modifiers>
{
typedef typename
result_of::compile<karma::domain, Padding, Modifiers>::type
padding_type;
typedef padding_right_alignment<Subject, padding_type, Width> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, Modifiers const& modifiers) const
{
return result_type(subject
, compile<karma::domain>(fusion::at_c<1>(term.args), modifiers)
, fusion::at_c<0>(term.args));
}
};
}}} // namespace boost::spirit::karma
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width>
struct has_semantic_action<karma::simple_right_alignment<Subject, Width> >
: unary_has_semantic_action<Subject> {};
template <typename Subject, typename Padding, typename Width>
struct has_semantic_action<
karma::padding_right_alignment<Subject, Padding, Width> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Width, typename Attribute
, typename Context, typename Iterator>
struct handles_container<
karma::simple_right_alignment<Subject, Width>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
template <typename Subject, typename Padding, typename Width
, typename Attribute, typename Context, typename Iterator>
struct handles_container<
karma::padding_right_alignment<Subject, Padding, Width>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,78 @@
// 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(SPIRIT_STRICT_RELAXED_APR_22_2010_0959AM)
#define SPIRIT_STRICT_RELAXED_APR_22_2010_0959AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/modify.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::strict> // enables strict[]
: mpl::true_ {};
template <>
struct use_directive<karma::domain, tag::relaxed> // enables relaxed[]
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <>
struct is_modifier_directive<karma::domain, tag::strict>
: mpl::true_ {};
template <>
struct is_modifier_directive<karma::domain, tag::relaxed>
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// Don't add tag::strict or tag::relaxed if there is already one of those
// in the modifier list
template <typename Current>
struct compound_modifier<Current, tag::strict
, typename enable_if<has_modifier<Current, tag::relaxed> >::type>
: Current
{
compound_modifier()
: Current() {}
compound_modifier(Current const& current, tag::strict const&)
: Current(current) {}
};
template <typename Current>
struct compound_modifier<Current, tag::relaxed
, typename enable_if<has_modifier<Current, tag::strict> >::type>
: Current
{
compound_modifier()
: Current() {}
compound_modifier(Current const& current, tag::relaxed const&)
: Current(current) {}
};
namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::strict;
using boost::spirit::relaxed;
#endif
using boost::spirit::strict_type;
using boost::spirit::relaxed_type;
}
}}
#endif
@@ -0,0 +1,85 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_UPPER_LOWER_CASE_JANUARY_19_2009_1142AM)
#define SPIRIT_UPPER_LOWER_CASE_JANUARY_19_2009_1142AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/modify.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding>
struct use_directive<
karma::domain, tag::char_code<tag::upper, CharEncoding> > // enables upper
: mpl::true_ {};
template <typename CharEncoding>
struct use_directive<
karma::domain, tag::char_code<tag::lower, CharEncoding> > // enables lower
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding>
struct is_modifier_directive<karma::domain
, tag::char_code<tag::upper, CharEncoding> >
: mpl::true_ {};
template <typename CharEncoding>
struct is_modifier_directive<karma::domain
, tag::char_code<tag::lower, CharEncoding> >
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// Don't add tag::upper or tag::lower if there is already one of those in
// the modifier list
template <typename Current, typename CharEncoding>
struct compound_modifier<
Current
, tag::char_code<tag::upper, CharEncoding>
, typename enable_if<
has_modifier<Current, tag::char_code<tag::lower, CharEncoding> >
>::type
>
: Current
{
compound_modifier()
: Current() {}
compound_modifier(Current const& current,
tag::char_code<tag::upper, CharEncoding> const&)
: Current(current) {}
};
template <typename Current, typename CharEncoding>
struct compound_modifier<
Current
, tag::char_code<tag::lower, CharEncoding>
, typename enable_if<
has_modifier<Current, tag::char_code<tag::upper, CharEncoding> >
>::type
>
: Current
{
compound_modifier()
: Current() {}
compound_modifier(Current const& current,
tag::char_code<tag::lower, CharEncoding> const&)
: Current(current) {}
};
}}
#endif
@@ -0,0 +1,114 @@
// 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_VERBATIM_MAR_02_2007_0303PM)
#define BOOST_SPIRIT_KARMA_VERBATIM_MAR_02_2007_0303PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/detail/unused_delimiter.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_directive<karma::domain, tag::verbatim> // enables verbatim[]
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::verbatim;
#endif
using spirit::verbatim_type;
///////////////////////////////////////////////////////////////////////////
// The verbatim generator is used for verbatim[...] directives.
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct verbatim_generator : unary_generator<verbatim_generator<Subject> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
verbatim_generator(Subject const& subject)
: subject(subject) {}
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// the verbatim generator simply dispatches to the embedded
// generator while supplying unused_delimiter as the new delimiter
// to avoid delimiting down the generator stream
typedef detail::unused_delimiter<Delimiter> unused_delimiter;
return subject.generate(sink, ctx, unused_delimiter(d), attr) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
info what(Context& context) const
{
return info("verbatim", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Modifiers>
struct make_directive<tag::verbatim, Subject, Modifiers>
{
typedef verbatim_generator<Subject> result_type;
result_type operator()(unused_type, Subject const& subject, unused_type) const
{
return result_type(subject);
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::verbatim_generator<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::verbatim_generator<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,74 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DOMAIN_FEB_20_2007_0943AM)
#define BOOST_SPIRIT_KARMA_DOMAIN_FEB_20_2007_0943AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/meta_compiler.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/preprocessor/cat.hpp>
namespace boost { namespace spirit { namespace karma
{
// karma's domain
struct domain {};
// bring in some of spirit parts into spirit::karma
using spirit::unused;
using spirit::unused_type;
using spirit::compile;
using spirit::info;
// You can bring these in with the using directive
// without worrying about bringing in too much.
namespace labels
{
BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _)
BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
using spirit::_pass_type;
using spirit::_val_type;
using spirit::_a_type;
using spirit::_b_type;
using spirit::_c_type;
using spirit::_d_type;
using spirit::_e_type;
using spirit::_f_type;
using spirit::_g_type;
using spirit::_h_type;
using spirit::_i_type;
using spirit::_j_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::_pass;
using spirit::_val;
using spirit::_a;
using spirit::_b;
using spirit::_c;
using spirit::_d;
using spirit::_e;
using spirit::_f;
using spirit::_g;
using spirit::_h;
using spirit::_i;
using spirit::_j;
#endif
}
}}}
#endif
@@ -0,0 +1,16 @@
// 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_FORMAT_DEC_01_2009_0716AM)
#define BOOST_SPIRIT_KARMA_FORMAT_DEC_01_2009_0716AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/stream/format_manip.hpp>
#include <boost/spirit/home/karma/stream/format_manip_attr.hpp>
#endif
@@ -0,0 +1,16 @@
// 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_FORMAT_AUTO_DEC_02_2009_1248PM)
#define BOOST_SPIRIT_KARMA_FORMAT_AUTO_DEC_02_2009_1248PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/stream/format_manip.hpp>
#include <boost/spirit/home/karma/stream/detail/format_manip_auto.hpp>
#endif
@@ -0,0 +1,232 @@
// 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_GENERATE_DEC_01_2009_0734PM)
#define BOOST_SPIRIT_KARMA_GENERATE_DEC_01_2009_0734PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/support/nonterminal/locals.hpp>
#include <boost/spirit/home/karma/detail/generate.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Expr>
inline bool
generate(
OutputIterator& sink
, Expr const& expr)
{
return detail::generate_impl<Expr>::call(sink, expr);
}
template <typename OutputIterator, typename Expr>
inline bool
generate(
OutputIterator const& sink_
, Expr const& expr)
{
OutputIterator sink = sink_;
return karma::generate(sink, expr);
}
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T>
struct make_context
{
typedef context<fusion::cons<T const&>, locals<> > type;
};
template <>
struct make_context<unused_type>
{
typedef unused_type type;
};
}
template <typename OutputIterator, typename Properties, typename Expr
, typename Attr>
inline bool
generate(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, Attr const& attr)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
typename detail::make_context<Attr>::type context(attr);
return compile<karma::domain>(expr).generate(sink, context, unused, attr);
}
template <typename OutputIterator, typename Expr, typename Attr>
inline bool
generate(
OutputIterator& sink_
, Expr const& expr
, Attr const& attr)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value> > sink(sink_);
return karma::generate(sink, expr, attr);
}
template <typename OutputIterator, typename Expr, typename Attr>
inline bool
generate(
OutputIterator const& sink_
, Expr const& expr
, Attr const& attr)
{
OutputIterator sink = sink_;
return karma::generate(sink, expr, attr);
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Expr, typename Delimiter>
inline bool
generate_delimited(
OutputIterator& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit =
delimit_flag::dont_predelimit)
{
return detail::generate_delimited_impl<Expr>::call(
sink, expr, delimiter, pre_delimit);
}
template <typename OutputIterator, typename Expr, typename Delimiter>
inline bool
generate_delimited(
OutputIterator const& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit =
delimit_flag::dont_predelimit)
{
OutputIterator sink = sink_;
return karma::generate_delimited(sink, expr, delimiter, pre_delimit);
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Expr
, typename Delimiter, typename Attribute>
inline bool
generate_delimited(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, Attribute const& attr)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then either the expression (expr) or skipper is not a valid
// spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typename result_of::compile<karma::domain, Delimiter>::type const
delimiter_ = compile<karma::domain>(delimiter);
if (pre_delimit == delimit_flag::predelimit &&
!karma::delimit_out(sink, delimiter_))
{
return false;
}
typename detail::make_context<Attribute>::type context(attr);
return compile<karma::domain>(expr).
generate(sink, context, delimiter_, attr);
}
template <typename OutputIterator, typename Expr, typename Delimiter
, typename Attribute>
inline bool
generate_delimited(
OutputIterator& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, Attribute const& attr)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
typedef traits::properties_of<
typename result_of::compile<karma::domain, Delimiter>::type
> delimiter_properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value | delimiter_properties::value>
> sink(sink_);
return karma::generate_delimited(sink, expr, delimiter, pre_delimit, attr);
}
template <typename OutputIterator, typename Expr, typename Delimiter
, typename Attribute>
inline bool
generate_delimited(
OutputIterator const& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, Attribute const& attr)
{
OutputIterator sink = sink_;
return karma::generate_delimited(sink, expr, delimiter, pre_delimit, attr);
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Expr, typename Delimiter
, typename Attribute>
inline bool
generate_delimited(
OutputIterator& sink
, Expr const& expr
, Delimiter const& delimiter
, Attribute const& attr)
{
return karma::generate_delimited(sink, expr, delimiter
, delimit_flag::dont_predelimit, attr);
}
template <typename OutputIterator, typename Expr, typename Delimiter
, typename Attribute>
inline bool
generate_delimited(
OutputIterator const& sink_
, Expr const& expr
, Delimiter const& delimiter
, Attribute const& attr)
{
OutputIterator sink = sink_;
return karma::generate_delimited(sink, expr, delimiter
, delimit_flag::dont_predelimit, attr);
}
}}}
#endif
@@ -0,0 +1,212 @@
// 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_PP_IS_ITERATING)
#if !defined(BOOST_SPIRIT_KARMA_GENERATE_ATTR_APR_23_2009_0541PM)
#define BOOST_SPIRIT_KARMA_GENERATE_ATTR_APR_23_2009_0541PM
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#define BOOST_PP_FILENAME_1 <boost/spirit/home/karma/generate_attr.hpp>
#define BOOST_PP_ITERATION_LIMITS (2, SPIRIT_ARGUMENTS_LIMIT)
#include BOOST_PP_ITERATE()
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Preprocessor vertical repetition code
//
///////////////////////////////////////////////////////////////////////////////
#else // defined(BOOST_PP_IS_ITERATING)
#define N BOOST_PP_ITERATION()
#define BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE(z, n, A) \
BOOST_PP_CAT(A, n) const&
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Expr
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
return compile<karma::domain>(expr).generate(sink, unused, unused, attr);
}
template <typename OutputIterator, typename Expr
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate(
OutputIterator& sink_
, Expr const& expr
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value> > sink(sink_);
return karma::generate(sink, expr, BOOST_PP_ENUM_PARAMS(N, attr));
}
template <typename OutputIterator, typename Expr
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate(
OutputIterator const& sink_
, Expr const& expr
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
OutputIterator sink = sink_;
return karma::generate(sink, expr, BOOST_PP_ENUM_PARAMS(N, attr));
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Expr
, typename Delimiter, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate_delimited(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then either the expression (expr) or skipper is not a valid
// spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typename result_of::compile<karma::domain, Delimiter>::type const
delimiter_ = compile<karma::domain>(delimiter);
if (pre_delimit == delimit_flag::predelimit &&
!karma::delimit_out(sink, delimiter_))
{
return false;
}
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
return compile<karma::domain>(expr).
generate(sink, unused, delimiter_, attr);
}
template <typename OutputIterator, typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate_delimited(
OutputIterator& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
typedef traits::properties_of<
typename result_of::compile<karma::domain, Delimiter>::type
> delimiter_properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value | delimiter_properties::value>
> sink(sink_);
return karma::generate_delimited(sink, expr, delimiter, pre_delimit
, BOOST_PP_ENUM_PARAMS(N, attr));
}
template <typename OutputIterator, typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate_delimited(
OutputIterator const& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
OutputIterator sink = sink_;
return karma::generate_delimited(sink, expr, delimiter, pre_delimit
, BOOST_PP_ENUM_PARAMS(N, attr));
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate_delimited(
OutputIterator& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
typedef traits::properties_of<
typename result_of::compile<karma::domain, Delimiter>::type
> delimiter_properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value | delimiter_properties::value>
> sink(sink_);
return karma::generate_delimited(sink, expr, delimiter
, delimit_flag::dont_predelimit, BOOST_PP_ENUM_PARAMS(N, attr));
}
template <typename OutputIterator, typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
generate_delimited(
OutputIterator const& sink_
, Expr const& expr
, Delimiter const& delimiter
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
OutputIterator sink = sink_;
return karma::generate_delimited(sink, expr, delimiter
, delimit_flag::dont_predelimit, BOOST_PP_ENUM_PARAMS(N, attr));
}
}}}
#undef BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE
#undef N
#endif // defined(BOOST_PP_IS_ITERATING)
@@ -0,0 +1,159 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_GENERATOR_JANUARY_13_2009_1002AM)
#define BOOST_SPIRIT_GENERATOR_JANUARY_13_2009_1002AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/int.hpp>
#include <boost/spirit/home/karma/domain.hpp>
namespace boost { namespace spirit { namespace karma
{
struct generator_properties
{
enum enum_type {
no_properties = 0,
buffering = 0x01, // generator requires buffering
counting = 0x02, // generator requires counting
tracking = 0x04, // generator requires position tracking
disabling = 0x08, // generator requires disabling of output
countingbuffer = 0x03, // buffering | counting
all_properties = 0x0f // buffering | counting | tracking | disabling
};
};
template <typename Derived>
struct generator
{
struct generator_id;
typedef mpl::int_<generator_properties::no_properties> properties;
typedef Derived derived_type;
typedef karma::domain domain;
// Requirement: g.generate(o, context, delimiter, attr) -> bool
//
// g: a generator
// o: output iterator
// context: enclosing rule context (can be unused_type)
// delimit: delimiter (can be unused_type)
// attr: attribute (can be unused_type)
// Requirement: g.what(context) -> info
//
// g: a generator
// context: enclosing rule context (can be unused_type)
// Requirement: G::template attribute<Ctx, Iter>::type
//
// G: a generator type
// Ctx: A context type (can be unused_type)
// Iter: An iterator type (always unused_type)
Derived const& derived() const
{
return *static_cast<Derived const*>(this);
}
};
template <typename Derived>
struct primitive_generator : generator<Derived>
{
struct primitive_generator_id;
};
template <typename Derived>
struct nary_generator : generator<Derived>
{
struct nary_generator_id;
// Requirement: g.elements -> fusion sequence
//
// g: a composite generator
// Requirement: G::elements_type -> fusion sequence
//
// G: a composite generator type
};
template <typename Derived>
struct unary_generator : generator<Derived>
{
struct unary_generator_id;
// Requirement: g.subject -> subject generator
//
// g: a unary generator
// Requirement: G::subject_type -> subject generator type
//
// G: a unary generator type
};
template <typename Derived>
struct binary_generator : generator<Derived>
{
struct binary_generator_id;
// Requirement: g.left -> left generator
//
// g: a binary generator
// Requirement: G::left_type -> left generator type
//
// G: a binary generator type
// Requirement: g.right -> right generator
//
// g: a binary generator
// Requirement: G::right_type -> right generator type
//
// G: a binary generator type
};
}}}
namespace boost { namespace spirit { namespace traits // classification
{
namespace detail
{
// generator tags
BOOST_MPL_HAS_XXX_TRAIT_DEF(generator_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(primitive_generator_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(nary_generator_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(unary_generator_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(binary_generator_id)
}
// check for generator tags
template <typename T>
struct is_generator : detail::has_generator_id<T> {};
template <typename T>
struct is_primitive_generator : detail::has_primitive_generator_id<T> {};
template <typename T>
struct is_nary_generator : detail::has_nary_generator_id<T> {};
template <typename T>
struct is_unary_generator : detail::has_unary_generator_id<T> {};
template <typename T>
struct is_binary_generator : detail::has_binary_generator_id<T> {};
// check for generator properties
template <typename T>
struct properties_of : T::properties {};
}}}
#endif
@@ -0,0 +1,177 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_META_COMPILER_JANUARY_13_2009_1011AM)
#define BOOST_SPIRIT_KARMA_META_COMPILER_JANUARY_13_2009_1011AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/meta_compiler.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/fusion/include/at.hpp>
namespace boost { namespace spirit
{
template <typename T>
struct use_terminal<karma::domain, T
, typename enable_if<traits::is_generator<T> >::type> // enables generators
: mpl::true_ {};
namespace karma
{
template <typename T, typename Modifiers, typename Enable = void>
struct make_primitive // by default, return it as-is
{
typedef T result_type;
template <typename T_>
T_& operator()(T_& val, unused_type) const
{
return val;
}
template <typename T_>
T_ const& operator()(T_ const& val, unused_type) const
{
return val;
}
};
template <typename Tag, typename Elements
, typename Modifiers, typename Enable = void>
struct make_composite;
template <typename Directive, typename Body
, typename Modifiers, typename Enable = void>
struct make_directive
{
typedef Body result_type;
result_type operator()(unused_type, Body const& body, unused_type) const
{
return body; // By default, a directive simply returns its subject
}
};
}
// Karma primitive meta-compiler
template <>
struct make_component<karma::domain, proto::tag::terminal>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename karma::make_primitive<
typename remove_const<typename Elements::car_type>::type
, typename remove_reference<Modifiers>::type
>::result_type type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
typedef typename remove_const<typename Elements::car_type>::type term;
return karma::make_primitive<term, Modifiers>()(elements.car, modifiers);
}
};
// Karma composite meta-compiler
template <typename Tag>
struct make_component<karma::domain, Tag>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
karma::make_composite<Tag, Elements
, typename remove_reference<Modifiers>::type>::result_type
type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
return karma::make_composite<Tag, Elements, Modifiers>()(
elements, modifiers);
}
};
// Karma function meta-compiler
template <>
struct make_component<karma::domain, proto::tag::function>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
karma::make_composite<
typename remove_const<typename Elements::car_type>::type,
typename Elements::cdr_type,
typename remove_reference<Modifiers>::type
>::result_type
type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
return karma::make_composite<
typename remove_const<typename Elements::car_type>::type,
typename Elements::cdr_type,
Modifiers>()(elements.cdr, modifiers);
}
};
// Karma directive meta-compiler
template <>
struct make_component<karma::domain, tag::directive>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
karma::make_directive<
typename remove_const<typename Elements::car_type>::type,
typename remove_const<typename Elements::cdr_type::car_type>::type,
typename remove_reference<Modifiers>::type
>::result_type
type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
return karma::make_directive<
typename remove_const<typename Elements::car_type>::type,
typename remove_const<typename Elements::cdr_type::car_type>::type,
Modifiers>()(elements.car, elements.cdr.car, modifiers);
}
};
}}
#endif
@@ -0,0 +1,18 @@
// 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_NONTERMINAL_MAR_05_2007_0539PM)
#define BOOST_SPIRIT_KARMA_NONTERMINAL_MAR_05_2007_0539PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/nonterminal/rule.hpp>
#include <boost/spirit/home/karma/nonterminal/grammar.hpp>
#include <boost/spirit/home/karma/nonterminal/debug_handler.hpp>
#include <boost/spirit/home/karma/nonterminal/simple_trace.hpp>
#endif
@@ -0,0 +1,134 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM)
#define BOOST_SPIRIT_KARMA_DEBUG_HANDLER_APR_21_2010_0148PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/nonterminal/rule.hpp>
#include <boost/spirit/home/karma/nonterminal/debug_handler_state.hpp>
#include <boost/function.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/out.hpp>
#include <iostream>
namespace boost { namespace spirit { namespace karma
{
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Properties, typename F>
struct debug_handler
{
typedef detail::output_iterator<OutputIterator, Properties>
output_iterator;
typedef detail::enable_buffering<output_iterator> buffer_type;
typedef function<bool(output_iterator&, Context&, Delimiter const&)>
function_type;
debug_handler(function_type subject, F f, std::string const& rule_name)
: subject(subject)
, f(f)
, rule_name(rule_name)
{}
bool operator()(output_iterator& sink, Context& context
, Delimiter const& delim) const
{
buffer_type buffer(sink);
bool r = false;
f (sink, context, pre_generate, rule_name, buffer);
{
detail::disable_counting<output_iterator> nocount(sink);
r = subject(sink, context, delim);
}
if (r)
{
f (sink, context, successful_generate, rule_name, buffer);
buffer.buffer_copy();
return true;
}
f (sink, context, failed_generate, rule_name, buffer);
return false;
}
function_type subject;
F f;
std::string rule_name;
};
template <typename OutputIterator
, typename T1, typename T2, typename T3, typename T4, typename F>
void debug(rule<OutputIterator, T1, T2, T3, T4>& r, F f)
{
typedef rule<OutputIterator, T1, T2, T3, T4> rule_type;
typedef
debug_handler<
OutputIterator
, typename rule_type::context_type
, typename rule_type::delimiter_type
, typename rule_type::properties
, F>
debug_handler;
r.f = debug_handler(r.f, f, r.name());
}
struct simple_trace;
namespace detail
{
// This class provides an extra level of indirection through a
// template to produce the simple_trace type. This way, the use
// of simple_trace below is hidden behind a dependent type, so
// that compilers eagerly type-checking template definitions
// won't complain that simple_trace is incomplete.
template<typename T>
struct get_simple_trace
{
typedef simple_trace type;
};
}
template <typename OutputIterator
, typename T1, typename T2, typename T3, typename T4>
void debug(rule<OutputIterator, T1, T2, T3, T4>& r)
{
typedef rule<OutputIterator, T1, T2, T3, T4> rule_type;
typedef
debug_handler<
OutputIterator
, typename rule_type::context_type
, typename rule_type::delimiter_type
, typename rule_type::properties
, simple_trace>
debug_handler;
typedef typename karma::detail::get_simple_trace<OutputIterator>::type
trace;
r.f = debug_handler(r.f, trace(), r.name());
}
}}}
///////////////////////////////////////////////////////////////////////////////
// Utility macro for easy enabling of rule and grammar debugging
#if !defined(BOOST_SPIRIT_DEBUG_NODE)
#if defined(BOOST_SPIRIT_KARMA_DEBUG)
#define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r); debug(r)
#else
#define BOOST_SPIRIT_DEBUG_NODE(r) r.name(#r);
#endif
#endif
#endif
@@ -0,0 +1,23 @@
// 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_DEBUG_HANDLER_STATE_APR_21_2010_0736PM)
#define BOOST_SPIRIT_KARMA_DEBUG_HANDLER_STATE_APR_21_2010_0736PM
#if defined(_MSC_VER)
#pragma once
#endif
namespace boost { namespace spirit { namespace karma
{
enum debug_handler_state
{
pre_generate
, successful_generate
, failed_generate
};
}}}
#endif
@@ -0,0 +1,53 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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)
#ifndef BOOST_PP_IS_ITERATING
#include <boost/preprocessor/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#define BOOST_PP_FILENAME_1 \
<boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
#define BOOST_PP_ITERATION_LIMITS (1, SPIRIT_ARGUMENTS_LIMIT)
#include BOOST_PP_ITERATE()
///////////////////////////////////////////////////////////////////////////////
//
// Preprocessor vertical repetition code
//
///////////////////////////////////////////////////////////////////////////////
#else // defined(BOOST_PP_IS_ITERATING)
#define N BOOST_PP_ITERATION()
template <BOOST_PP_ENUM_PARAMS(N, typename A)>
typename lazy_enable_if_c<
(params_size == N)
, proto::terminal<
spirit::karma::parameterized_nonterminal<
parameterized_subject_type
, fusion::vector<BOOST_PP_ENUM_PARAMS(N, A)> >
>
>::type
operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& f)) const
{
typedef fusion::vector<BOOST_PP_ENUM_PARAMS(N, A)> vector_type;
typedef spirit::karma::parameterized_nonterminal<
parameterized_subject_type, vector_type> parameterized_type;
typedef typename proto::terminal<parameterized_type>::type result_type;
return result_type::make(
parameterized_type(
this->get_parameterized_subject()
, fusion::make_vector(BOOST_PP_ENUM_PARAMS(N, f)))
);
}
#undef N
#endif // defined(BOOST_PP_IS_ITERATING)
@@ -0,0 +1,86 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_GENERATOR_BINDER_APR_17_2009_0952PM)
#define BOOST_SPIRIT_GENERATOR_BINDER_APR_17_2009_0952PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
// generator_binder for plain rules
template <typename Generator, typename Auto>
struct generator_binder
{
generator_binder(Generator const& g)
: g(g) {}
template <typename OutputIterator, typename Delimiter, typename Context>
bool call(OutputIterator& sink, Context& context
, Delimiter const& delim, mpl::true_) const
{
// If DeducedAuto is false (semantic actions is present), the
// component's attribute is unused.
return g.generate(sink, context, delim, unused);
}
template <typename OutputIterator, typename Delimiter, typename Context>
bool call(OutputIterator& sink, Context& context
, Delimiter const& delim, mpl::false_) const
{
// If DeducedAuto is true (no semantic action), we pass the rule's
// attribute on to the component.
return g.generate(sink, context, delim
, fusion::at_c<0>(context.attributes));
}
template <typename OutputIterator, typename Delimiter, typename Context>
bool operator()(OutputIterator& sink, Context& context
, Delimiter const& delim) const
{
// If Auto is false, we need to deduce whether to apply auto rule
typedef typename traits::has_semantic_action<Generator>::type auto_rule;
return call(sink, context, delim, auto_rule());
}
Generator g;
};
// generator_binder for auto rules
template <typename Generator>
struct generator_binder<Generator, mpl::true_>
{
generator_binder(Generator const& g)
: g(g) {}
template <typename OutputIterator, typename Delimiter, typename Context>
bool operator()(OutputIterator& sink, Context& context
, Delimiter const& delim) const
{
// If Auto is true, the component's attribute is unused.
return g.generate(sink, context, delim
, fusion::at_c<0>(context.attributes));
}
Generator g;
};
template <typename Auto, typename Generator>
inline generator_binder<Generator, Auto>
bind_generator(Generator const& g)
{
return generator_binder<Generator, Auto>(g);
}
}}}}
#endif
@@ -0,0 +1,76 @@
// Copyright (c) 2001-2011 Joel de Guzman
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2009 Francois Barel
//
// 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_PARAMETERIZED_AUGUST_09_2009_0601AM)
#define BOOST_SPIRIT_KARMA_PARAMETERIZED_AUGUST_09_2009_0601AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/ref.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/generator.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// parameterized_nonterminal: generator representing the invocation of a
// nonterminal, passing inherited attributes
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Params>
struct parameterized_nonterminal
: generator<parameterized_nonterminal<Subject, Params> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
parameterized_nonterminal(Subject const& subject, Params const& params)
: ref(subject), params(params)
{
}
template <typename Context, typename Unused>
struct attribute
// Forward to subject.
: Subject::template attribute<Context, Unused> {};
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& delim, Attribute const& attr) const
{
// Forward to subject, passing the additional
// params argument to generate.
return ref.get().generate(sink, context, delim, attr, params);
}
template <typename Context>
info what(Context& context) const
{
// Forward to subject.
return ref.get().what(context);
}
boost::reference_wrapper<Subject const> ref;
Params params;
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Params, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::parameterized_nonterminal<Subject, Params>
, Attribute, Context, Iterator>
: handles_container<typename remove_const<Subject>::type
, Attribute, Context, Iterator>
{};
}}}
#endif
@@ -0,0 +1,134 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_GRAMMAR_MAR_05_2007_0542PM)
#define BOOST_SPIRIT_KARMA_GRAMMAR_MAR_05_2007_0542PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/assert_msg.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/nonterminal/rule.hpp>
#include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp>
#include <boost/spirit/home/karma/reference.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost { namespace spirit { namespace karma
{
template <
typename OutputIterator, typename T1, typename T2, typename T3
, typename T4>
struct grammar
: proto::extends<
typename proto::terminal<
reference<rule<OutputIterator, T1, T2, T3, T4> const>
>::type
, grammar<OutputIterator, T1, T2, T3, T4>
>
, generator<grammar<OutputIterator, T1, T2, T3, T4> >
, noncopyable
{
typedef OutputIterator iterator_type;
typedef rule<OutputIterator, T1, T2, T3, T4> start_type;
typedef typename start_type::properties properties;
typedef typename start_type::sig_type sig_type;
typedef typename start_type::locals_type locals_type;
typedef typename start_type::delimiter_type delimiter_type;
typedef typename start_type::encoding_type encoding_type;
typedef grammar<OutputIterator, T1, T2, T3, T4> base_type;
typedef reference<start_type const> reference_;
typedef typename proto::terminal<reference_>::type terminal;
static size_t const params_size = start_type::params_size;
template <typename Context, typename Unused>
struct attribute
{
typedef typename start_type::attr_type type;
};
// the output iterator is always wrapped by karma
typedef detail::output_iterator<OutputIterator, properties>
output_iterator;
grammar(start_type const& start
, std::string const& name_ = "unnamed-grammar")
: proto::extends<terminal, base_type>(terminal::make(reference_(start)))
, name_(name_)
{}
// This constructor is used to catch if the start rule is not
// compatible with the grammar.
template <typename Iterator_, typename T1_, typename T2_, typename T3_,
typename T4_>
grammar(rule<Iterator_, T1_, T2_, T3_, T4_> const&
, std::string const& = "unnamed-grammar")
{
// If you see the assertion below failing then the start rule
// passed to the constructor of the grammar is not compatible with
// the grammar (i.e. it uses different template parameters).
BOOST_SPIRIT_ASSERT_MSG(
(is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value)
, incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>));
}
std::string name() const
{
return name_;
}
void name(std::string const& str)
{
name_ = str;
}
template <typename Context, typename Delimiter, typename Attribute>
bool generate(output_iterator& sink, Context& context
, Delimiter const& delim, Attribute const& attr) const
{
return this->proto_base().child0.generate(
sink, context, delim, attr);
}
template <typename Context>
info what(Context&) const
{
return info(name_);
}
// bring in the operator() overloads
start_type const& get_parameterized_subject() const
{ return this->proto_base().child0.ref.get(); }
typedef start_type parameterized_subject_type;
#include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
std::string name_;
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <
typename IteratorA, typename IteratorB, typename Attribute
, typename Context, typename T1, typename T2, typename T3, typename T4>
struct handles_container<
karma::grammar<IteratorA, T1, T2, T3, T4>, Attribute, Context
, IteratorB>
: detail::nonterminal_handles_container<
typename attribute_of<
karma::grammar<IteratorA, T1, T2, T3, T4>
, Context, IteratorB
>::type, Attribute>
{};
}}}
#endif
@@ -0,0 +1,31 @@
// 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_NONTERMINAL_FWD_DEC_18_2010_0913PM)
#define BOOST_SPIRIT_KARMA_NONTERMINAL_FWD_DEC_18_2010_0913PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
namespace boost { namespace spirit { namespace karma
{
// forward declaration only
template <
typename OutputIterator, typename T1 = unused_type
, typename T2 = unused_type, typename T3 = unused_type
, typename T4 = unused_type>
struct rule;
template <
typename OutputIterator, typename T1 = unused_type
, typename T2 = unused_type, typename T3 = unused_type
, typename T4 = unused_type>
struct grammar;
}}}
#endif
@@ -0,0 +1,448 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_RULE_MAR_05_2007_0455PM)
#define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0455PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/function.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/make_vector.hpp>
#include <boost/fusion/include/cons.hpp>
#include <boost/fusion/include/as_list.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/context.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/nonterminal/extract_param.hpp>
#include <boost/spirit/home/support/nonterminal/locals.hpp>
#include <boost/spirit/home/karma/reference.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp>
#include <boost/spirit/home/karma/nonterminal/detail/generator_binder.hpp>
#include <boost/spirit/home/karma/nonterminal/detail/parameterized.hpp>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
#endif
namespace boost { namespace spirit { namespace karma
{
BOOST_PP_REPEAT(SPIRIT_ATTRIBUTES_LIMIT, SPIRIT_USING_ATTRIBUTE, _)
using spirit::_pass_type;
using spirit::_val_type;
using spirit::_a_type;
using spirit::_b_type;
using spirit::_c_type;
using spirit::_d_type;
using spirit::_e_type;
using spirit::_f_type;
using spirit::_g_type;
using spirit::_h_type;
using spirit::_i_type;
using spirit::_j_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::_pass;
using spirit::_val;
using spirit::_a;
using spirit::_b;
using spirit::_c;
using spirit::_d;
using spirit::_e;
using spirit::_f;
using spirit::_g;
using spirit::_h;
using spirit::_i;
using spirit::_j;
#endif
using spirit::info;
using spirit::locals;
template <
typename OutputIterator, typename T1, typename T2, typename T3
, typename T4>
struct rule
: proto::extends<
typename proto::terminal<
reference<rule<OutputIterator, T1, T2, T3, T4> const>
>::type
, rule<OutputIterator, T1, T2, T3, T4>
>
, generator<rule<OutputIterator, T1, T2, T3, T4> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
typedef OutputIterator iterator_type;
typedef rule<OutputIterator, T1, T2, T3, T4> this_type;
typedef reference<this_type const> reference_;
typedef typename proto::terminal<reference_>::type terminal;
typedef proto::extends<terminal, this_type> base_type;
typedef mpl::vector<T1, T2, T3, T4> template_params;
// the output iterator is always wrapped by karma
typedef detail::output_iterator<OutputIterator, properties>
output_iterator;
// locals_type is a sequence of types to be used as local variables
typedef typename
spirit::detail::extract_locals<template_params>::type
locals_type;
// The delimiter-generator type
typedef typename
spirit::detail::extract_component<
karma::domain, template_params>::type
delimiter_type;
// The rule's encoding type
typedef typename
spirit::detail::extract_encoding<template_params>::type
encoding_type;
// The rule's signature
typedef typename
spirit::detail::extract_sig<template_params, encoding_type, karma::domain>::type
sig_type;
// This is the rule's attribute type
typedef typename
spirit::detail::attr_from_sig<sig_type>::type
attr_type;
typedef typename add_reference<
typename add_const<attr_type>::type>::type
attr_reference_type;
// parameter_types is a sequence of types passed as parameters to the rule
typedef typename
spirit::detail::params_from_sig<sig_type>::type
parameter_types;
static size_t const params_size =
fusion::result_of::size<parameter_types>::type::value;
// the context passed to the right hand side of a rule contains
// the attribute and the parameters for this particular rule invocation
typedef context<
fusion::cons<attr_reference_type, parameter_types>
, locals_type>
context_type;
typedef function<
bool(output_iterator&, context_type&, delimiter_type const&)>
function_type;
typedef typename
mpl::if_<
is_same<encoding_type, unused_type>
, unused_type
, tag::char_code<tag::encoding, encoding_type>
>::type
encoding_modifier_type;
explicit rule(std::string const& name_ = "unnamed-rule")
: base_type(terminal::make(reference_(*this)))
, name_(name_)
{
}
rule(rule const& rhs)
: base_type(terminal::make(reference_(*this)))
, name_(rhs.name_)
, f(rhs.f)
{
}
template <typename Auto, typename Expr>
static void define(rule& lhs, Expr const& expr, mpl::false_)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
}
template <typename Auto, typename Expr>
static void define(rule& lhs, Expr const& expr, mpl::true_)
{
lhs.f = detail::bind_generator<Auto>(
compile<karma::domain>(expr, encoding_modifier_type()));
}
template <typename Expr>
rule (Expr const& expr, std::string const& name_ = "unnamed-rule")
: base_type(terminal::make(reference_(*this)))
, name_(name_)
{
define<mpl::false_>(*this, expr, traits::matches<karma::domain, Expr>());
}
rule& operator=(rule const& rhs)
{
// The following assertion fires when you try to initialize a rule
// from an uninitialized one. Did you mean to refer to the right
// hand side rule instead of assigning from it? In this case you
// should write lhs = rhs.alias();
BOOST_ASSERT(rhs.f && "Did you mean rhs.alias() instead of rhs?");
f = rhs.f;
name_ = rhs.name_;
return *this;
}
std::string const& name() const
{
return name_;
}
void name(std::string const& str)
{
name_ = str;
}
template <typename Expr>
rule& operator=(Expr const& expr)
{
define<mpl::false_>(*this, expr, traits::matches<karma::domain, Expr>());
return *this;
}
// VC7.1 has problems to resolve 'rule' without explicit template parameters
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1400)
// g++ 3.3 barfs if this is a member function :(
template <typename Expr>
friend rule& operator%=(rule& r, Expr const& expr)
{
define<mpl::true_>(r, expr, traits::matches<karma::domain, Expr>());
return r;
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// non-const version needed to suppress proto's %= kicking in
template <typename Expr>
friend rule& operator%=(rule& r, Expr& expr)
{
return r %= static_cast<Expr const&>(expr);
}
#else
// for rvalue references
template <typename Expr>
friend rule& operator%=(rule& r, Expr&& expr)
{
define<mpl::true_>(r, expr, traits::matches<karma::domain, Expr>());
return r;
}
#endif
#else
// both friend functions have to be defined out of class as VC7.1
// will complain otherwise
template <typename OutputIterator_, typename T1_, typename T2_
, typename T3_, typename T4_, typename Expr>
friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
rule<OutputIterator_, T1_, T2_, T3_, T4_>&r, Expr const& expr);
// non-const version needed to suppress proto's %= kicking in
template <typename OutputIterator_, typename T1_, typename T2_
, typename T3_, typename T4_, typename Expr>
friend rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr);
#endif
template <typename Context, typename Unused>
struct attribute
{
typedef attr_type type;
};
template <typename Context, typename Delimiter, typename Attribute>
bool generate(output_iterator& sink, Context&, Delimiter const& delim
, Attribute const& attr) const
{
if (f)
{
// Create an attribute if none is supplied.
typedef traits::make_attribute<attr_type, Attribute>
make_attribute;
typedef traits::transform_attribute<
typename make_attribute::type, attr_type, domain>
transform;
typename transform::type attr_ =
traits::pre_transform<domain, attr_type>(
make_attribute::call(attr));
// If you are seeing a compilation error here, you are probably
// trying to use a rule or a grammar which has inherited
// attributes, without passing values for them.
context_type context(attr_);
// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.
if (f(sink, context, delim))
{
// do a post-delimit if this is an implied verbatim
if (is_same<delimiter_type, unused_type>::value)
karma::delimit_out(sink, delim);
return true;
}
}
return false;
}
template <typename Context, typename Delimiter, typename Attribute
, typename Params>
bool generate(output_iterator& sink, Context& caller_context
, Delimiter const& delim, Attribute const& attr
, Params const& params) const
{
if (f)
{
// Create an attribute if none is supplied.
typedef traits::make_attribute<attr_type, Attribute>
make_attribute;
typedef traits::transform_attribute<
typename make_attribute::type, attr_type, domain>
transform;
typename transform::type attr_ =
traits::pre_transform<domain, attr_type>(
make_attribute::call(attr));
// If you are seeing a compilation error here, you are probably
// trying to use a rule or a grammar which has inherited
// attributes, passing values of incompatible types for them.
context_type context(attr_, params, caller_context);
// If you are seeing a compilation error here stating that the
// third parameter can't be converted to a karma::reference
// then you are probably trying to use a rule or a grammar with
// an incompatible delimiter type.
if (f(sink, context, delim))
{
// do a post-delimit if this is an implied verbatim
if (is_same<delimiter_type, unused_type>::value)
karma::delimit_out(sink, delim);
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info(name_);
}
reference_ alias() const
{
return reference_(*this);
}
typename proto::terminal<this_type>::type copy() const
{
typename proto::terminal<this_type>::type result = {*this};
return result;
}
// bring in the operator() overloads
rule const& get_parameterized_subject() const { return *this; }
typedef rule parameterized_subject_type;
#include <boost/spirit/home/karma/nonterminal/detail/fcall.hpp>
std::string name_;
function_type f;
};
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
template <typename OutputIterator_, typename T1_, typename T2_
, typename T3_, typename T4_, typename Expr>
rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
rule<OutputIterator_, T1_, T2_, T3_, T4_>&r, Expr const& expr)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here, then
// the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
typedef typename
rule<OutputIterator_, T1_, T2_, T3_, T4_>::encoding_modifier_type
encoding_modifier_type;
r.f = detail::bind_generator<mpl::true_>(
compile<karma::domain>(expr, encoding_modifier_type()));
return r;
}
// non-const version needed to suppress proto's %= kicking in
template <typename OutputIterator_, typename T1_, typename T2_
, typename T3_, typename T4_, typename Expr>
rule<OutputIterator_, T1_, T2_, T3_, T4_>& operator%=(
rule<OutputIterator_, T1_, T2_, T3_, T4_>& r, Expr& expr)
{
return r %= static_cast<Expr const&>(expr);
}
#endif
}}}
namespace boost { namespace spirit { namespace traits
{
namespace detail
{
template <typename RuleAttribute, typename Attribute>
struct nonterminal_handles_container
: mpl::and_<
traits::is_container<RuleAttribute>
, is_convertible<Attribute, RuleAttribute> >
{};
}
///////////////////////////////////////////////////////////////////////////
template <
typename IteratorA, typename IteratorB, typename Attribute
, typename Context, typename T1, typename T2, typename T3, typename T4>
struct handles_container<
karma::rule<IteratorA, T1, T2, T3, T4>, Attribute, Context
, IteratorB>
: detail::nonterminal_handles_container<
typename attribute_of<
karma::rule<IteratorA, T1, T2, T3, T4>
, Context, IteratorB
>::type, Attribute>
{};
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif
@@ -0,0 +1,134 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_SIMPLE_TRACE_APR_21_2010_0155PM)
#define BOOST_SPIRIT_KARMA_SIMPLE_TRACE_APR_21_2010_0155PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/nonterminal/debug_handler_state.hpp>
#include <boost/fusion/include/out.hpp>
#include <iostream>
// The stream to use for debug output
#if !defined(BOOST_SPIRIT_DEBUG_OUT)
#define BOOST_SPIRIT_DEBUG_OUT std::cerr
#endif
// number of tokens to print while debugging
#if !defined(BOOST_SPIRIT_DEBUG_PRINT_SOME)
#define BOOST_SPIRIT_DEBUG_PRINT_SOME 20
#endif
// number of spaces to indent
#if !defined(BOOST_SPIRIT_DEBUG_INDENT)
#define BOOST_SPIRIT_DEBUG_INDENT 2
#endif
namespace boost { namespace spirit { namespace karma
{
struct simple_trace
{
int& get_indent() const
{
static int indent = 0;
return indent;
}
void print_indent() const
{
int n = get_indent();
n *= BOOST_SPIRIT_DEBUG_INDENT;
for (int i = 0; i != n; ++i)
BOOST_SPIRIT_DEBUG_OUT << ' ';
}
template <typename Buffer>
void print_some(char const* tag, Buffer const& buffer) const
{
print_indent();
BOOST_SPIRIT_DEBUG_OUT << '<' << tag << '>' << std::flush;
{
std::ostreambuf_iterator<char> out(BOOST_SPIRIT_DEBUG_OUT);
buffer.buffer_copy_to(out, BOOST_SPIRIT_DEBUG_PRINT_SOME);
}
BOOST_SPIRIT_DEBUG_OUT << "</" << tag << '>' << std::endl;
}
template <typename OutputIterator, typename Context, typename State
, typename Buffer>
void operator()(
OutputIterator&, Context const& context
, State state, std::string const& rule_name
, Buffer const& buffer) const
{
switch (state)
{
case pre_generate:
print_indent();
++get_indent();
BOOST_SPIRIT_DEBUG_OUT
<< '<' << rule_name << '>' << std::endl;
print_indent();
++get_indent();
BOOST_SPIRIT_DEBUG_OUT << "<try>" << std::endl;;
print_indent();
BOOST_SPIRIT_DEBUG_OUT << "<attributes>";
traits::print_attribute(
BOOST_SPIRIT_DEBUG_OUT,
context.attributes
);
BOOST_SPIRIT_DEBUG_OUT << "</attributes>" << std::endl;
if (!fusion::empty(context.locals))
{
print_indent();
BOOST_SPIRIT_DEBUG_OUT
<< "<locals>" << context.locals << "</locals>"
<< std::endl;
}
--get_indent();
print_indent();
BOOST_SPIRIT_DEBUG_OUT << "</try>" << std::endl;;
break;
case successful_generate:
print_indent();
++get_indent();
BOOST_SPIRIT_DEBUG_OUT << "<success>" << std::endl;
print_some("result", buffer);
if (!fusion::empty(context.locals))
{
print_indent();
BOOST_SPIRIT_DEBUG_OUT
<< "<locals>" << context.locals << "</locals>"
<< std::endl;
}
--get_indent();
print_indent();
BOOST_SPIRIT_DEBUG_OUT << "</success>" << std::endl;
--get_indent();
print_indent();
BOOST_SPIRIT_DEBUG_OUT
<< "</" << rule_name << '>' << std::endl;
break;
case failed_generate:
print_indent();
BOOST_SPIRIT_DEBUG_OUT << "<fail/>" << std::endl;
--get_indent();
print_indent();
BOOST_SPIRIT_DEBUG_OUT
<< "</" << rule_name << '>' << std::endl;
break;
}
}
};
}}}
#endif
@@ -0,0 +1,18 @@
// 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_FEB_23_2007_0507PM)
#define BOOST_SPIRIT_KARMA_NUMERIC_FEB_23_2007_0507PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/numeric/bool.hpp>
#include <boost/spirit/home/karma/numeric/int.hpp>
#include <boost/spirit/home/karma/numeric/uint.hpp>
#include <boost/spirit/home/karma/numeric/real.hpp>
#endif
@@ -0,0 +1,424 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM)
#define BOOST_SPIRIT_KARMA_BOOL_SEP_28_2009_1113AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/bool_policies.hpp>
#include <boost/spirit/home/karma/numeric/detail/bool_utils.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
namespace karma
{
///////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename T>
struct bool_policies;
///////////////////////////////////////////////////////////////////////
// This is the class that the user can instantiate directly in
// order to create a customized bool generator
template <typename T = bool, typename Policies = bool_policies<T> >
struct bool_generator
: spirit::terminal<tag::stateful_tag<Policies, tag::bool_, T> >
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
bool_generator() {}
bool_generator(Policies const& data)
: spirit::terminal<tag_type>(data) {}
};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::bool_> // enables bool_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::true_> // enables true_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::false_> // enables false_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, bool> // enables lit(true)
: mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables bool_(...)
, terminal_ex<tag::bool_, fusion::vector1<A0> >
> : mpl::true_ {};
template <> // enables *lazy* bool_(...)
struct use_lazy_terminal<karma::domain, tag::bool_, 1>
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// enables any custom bool_generator
template <typename Policies, typename T>
struct use_terminal<karma::domain
, tag::stateful_tag<Policies, tag::bool_, T> >
: mpl::true_ {};
// enables any custom bool_generator(...)
template <typename Policies, typename T, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
, fusion::vector1<A0> > >
: mpl::true_ {};
// enables *lazy* custom bool_generator
template <typename Policies, typename T>
struct use_lazy_terminal<karma::domain
, tag::stateful_tag<Policies, tag::bool_, T>, 1>
: mpl::true_ {};
// enables lit(bool)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_bool<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::bool_;
using spirit::true_;
using spirit::false_;
using spirit::lit; // lit(true) is equivalent to true
#endif
using spirit::bool_type;
using spirit::true_type;
using spirit::false_type;
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for bool generators not having a direct
// initializer: bool_. These generators must be used in conjunction with
// an Attribute.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag, typename Policies>
struct any_bool_generator
: primitive_generator<any_bool_generator<T, CharEncoding, Tag, Policies> >
{
public:
any_bool_generator(Policies const& p = Policies())
: p_(p) {}
typedef typename Policies::properties properties;
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// bool_ has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr) const
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return bool_inserter<T, Policies, CharEncoding, Tag>::call(
sink, traits::extract_from<T>(attr, context), p_) &&
delimit_out(sink, d); // always do post-delimiting
}
// this bool_ has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use boolean generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, bool_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("bool");
}
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for bool generators having a direct
// initializer: bool_(true), bool_(0) etc.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag
, typename Policies, bool no_attribute>
struct literal_bool_generator
: primitive_generator<literal_bool_generator<T, CharEncoding, Tag
, Policies, no_attribute> >
{
public:
typedef typename Policies::properties properties;
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_bool_generator(typename add_const<T>::type n
, Policies const& p = Policies())
: n_(n), p_(p) {}
// A bool_() which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
bool(n_) != bool(traits::extract_from<attribute_type>(attr, context)))
{
return false;
}
return bool_inserter<T, Policies, CharEncoding, Tag>::
call(sink, n_, p_) && delimit_out(sink, d);
}
// A bool_() without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return bool_inserter<T, Policies, CharEncoding, Tag>::
call(sink, n_) && delimit_out(sink, d);
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("bool");
}
T n_;
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers, typename T = bool
, typename Policies = bool_policies<T> >
struct make_bool
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_bool_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Policies
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term));
}
};
template <typename Modifiers, bool b>
struct make_bool_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, false
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type(b);
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::bool_, Modifiers>
: detail::make_bool<Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::true_, Modifiers>
: detail::make_bool_literal<Modifiers, true> {};
template <typename Modifiers>
struct make_primitive<tag::false_, Modifiers>
: detail::make_bool_literal<Modifiers, false> {};
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::bool_, T>, Modifiers>
: detail::make_bool<Modifiers
, typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers, typename T = bool
, typename Policies = bool_policies<T> >
struct make_bool_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Policies, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::bool_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(fusion::at_c<0>(term.args)
, get_stateful_data<tag_type>::call(term.term));
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::bool_, fusion::vector1<A0> >, Modifiers>
: detail::make_bool_direct<Modifiers> {};
template <typename T, typename Policies, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::stateful_tag<Policies, tag::bool_, T>
, fusion::vector1<A0> >
, Modifiers>
: detail::make_bool_direct<Modifiers
, typename remove_const<T>::type, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Modifiers>
struct basic_bool_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
template <typename Modifiers>
struct make_primitive<bool, Modifiers>
: detail::basic_bool_literal<Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_bool<A0> >::type>
: detail::basic_bool_literal<Modifiers>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_bool_generator<
bool
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, bool_policies<>, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif
@@ -0,0 +1,117 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_POLICIES_SEP_28_2009_1203PM)
#define BOOST_SPIRIT_KARMA_BOOL_POLICIES_SEP_28_2009_1203PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// bool_policies, if you need special handling of your boolean output
// just overload this policy class and use it as a template
// parameter to the karma::bool_generator boolean generator
//
// struct special_bool_policy : karma::bool_policies<>
// {
// // we want to spell the names of false as eurt (true backwards)
// template <typename CharEncoding, typename Tag
// , typename OutputIterator>
// static bool generate_false(OutputIterator& sink, bool)
// {
// return string_inserter<CharEncoding, Tag>::call(sink, "eurt");
// }
// };
//
// typedef karma::bool_generator<special_bool_policy> backwards_bool;
//
// karma::generate(sink, backwards_bool(), false); // will output: eurt
//
///////////////////////////////////////////////////////////////////////////
template <typename T = bool>
struct bool_policies
{
///////////////////////////////////////////////////////////////////////
// Expose the data type the generator is targeted at
///////////////////////////////////////////////////////////////////////
typedef T value_type;
///////////////////////////////////////////////////////////////////////
// By default the policy doesn't require any special iterator
// functionality. The boolean generator exposes its properties
// from here, so this needs to be updated in case other properties
// need to be implemented.
///////////////////////////////////////////////////////////////////////
typedef mpl::int_<generator_properties::no_properties> properties;
///////////////////////////////////////////////////////////////////////
// This is the main function used to generate the output for a
// boolean. It is called by the boolean generator in order
// to perform the conversion. In theory all of the work can be
// implemented here, but it is the easiest to use existing
// functionality provided by the type specified by the template
// parameter `Inserter`.
//
// sink: the output iterator to use for generation
// n: the floating point number to convert
// p: the instance of the policy type used to instantiate this
// floating point generator.
///////////////////////////////////////////////////////////////////////
template <typename Inserter, typename OutputIterator, typename Policies>
static bool
call (OutputIterator& sink, T n, Policies const& p)
{
return Inserter::call_n(sink, n, p);
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations of a true boolean value
//
// sink The output iterator to use for generation
// b The boolean value to convert.
//
// The CharEncoding and Tag template parameters are either of the type
// unused_type or describes the character class and conversion to be
// applied to any output possibly influenced by either the lower[...]
// or upper[...] directives.
//
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool generate_true(OutputIterator& sink, T)
{
return string_inserter<CharEncoding, Tag>::call(sink, "true");
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations of a false boolean value
//
// sink The output iterator to use for generation
// b The boolean value to convert.
//
// The CharEncoding and Tag template parameters are either of the type
// unused_type or describes the character class and conversion to be
// applied to any output possibly influenced by either the lower[...]
// or upper[...] directives.
//
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool generate_false(OutputIterator& sink, T)
{
return string_inserter<CharEncoding, Tag>::call(sink, "false");
}
};
}}}
#endif
@@ -0,0 +1,67 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_BOOL_UTILS_SEP_28_2009_0644PM)
#define BOOST_SPIRIT_KARMA_BOOL_UTILS_SEP_28_2009_0644PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/detail/workaround.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The bool_inserter template takes care of the boolean to string
// conversion. The Policies template parameter is used to allow
// customization of the formatting process
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct bool_policies;
template <typename T
, typename Policies = bool_policies<T>
, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct bool_inserter
{
template <typename OutputIterator, typename U>
static bool
call (OutputIterator& sink, U b, Policies const& p = Policies())
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
p; // suppresses warning: C4100: 'p' : unreferenced formal parameter
#endif
return p.template call<bool_inserter>(sink, T(b), p);
}
///////////////////////////////////////////////////////////////////////
// This is the workhorse behind the real generator
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename U>
static bool
call_n (OutputIterator& sink, U b, Policies const& p)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
p; // suppresses warning: C4100: 'p' : unreferenced formal parameter
#endif
if (b)
return p.template generate_true<CharEncoding, Tag>(sink, b);
return p.template generate_false<CharEncoding, Tag>(sink, b);
}
};
}}}
#endif
@@ -0,0 +1,774 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
#define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/detail/pow10.hpp>
#include <boost/spirit/home/support/detail/sign.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
// integer string generation loop (see below).
//
// Set the value to some integer in between 0 (no unrolling) and the
// largest expected generated integer string length (complete unrolling).
// If not specified, this value defaults to 6.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
#define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
#endif
#if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
#error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a non-negative value!"
#endif
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////
//
// return the absolute value from a given number, avoiding over- and
// underflow
//
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct absolute_value
{
typedef T type;
static T call (T n)
{
// allow for ADL to find the correct overloads for fabs
using namespace std;
return fabs(n);
}
};
#define BOOST_SPIRIT_ABSOLUTE_VALUE(signedtype, unsignedtype) \
template <> \
struct absolute_value<signedtype> \
{ \
typedef unsignedtype type; \
static type call(signedtype n) \
{ \
return (n >= 0) ? n : (unsignedtype)(-n); \
} \
} \
/**/
#define BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsignedtype) \
template <> \
struct absolute_value<unsignedtype> \
{ \
typedef unsignedtype type; \
static type call(unsignedtype n) \
{ \
return n; \
} \
} \
/**/
BOOST_SPIRIT_ABSOLUTE_VALUE(signed char, unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE(char, unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE(short, unsigned short);
BOOST_SPIRIT_ABSOLUTE_VALUE(int, unsigned int);
BOOST_SPIRIT_ABSOLUTE_VALUE(long, unsigned long);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned char);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned short);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned int);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned long);
#ifdef BOOST_HAS_LONG_LONG
BOOST_SPIRIT_ABSOLUTE_VALUE(boost::long_long_type, boost::ulong_long_type);
BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(boost::ulong_long_type);
#endif
#undef BOOST_SPIRIT_ABSOLUTE_VALUE
#undef BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED
template <>
struct absolute_value<float>
{
typedef float type;
static type call(float n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
template <>
struct absolute_value<double>
{
typedef double type;
static type call(double n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
template <>
struct absolute_value<long double>
{
typedef long double type;
static type call(long double n)
{
return (spirit::detail::signbit)(n) ? -n : n;
}
};
// specialization for pointers
template <typename T>
struct absolute_value<T*>
{
typedef std::size_t type;
static type call (T* p)
{
return std::size_t(p);
}
};
template <typename T>
inline typename absolute_value<T>::type
get_absolute_value(T n)
{
return absolute_value<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_negative
{
static bool call(T n)
{
return (n < 0) ? true : false;
}
};
template <>
struct is_negative<float>
{
static bool call(float n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <>
struct is_negative<double>
{
static bool call(double n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <>
struct is_negative<long double>
{
static bool call(long double n)
{
return (spirit::detail::signbit)(n) ? true : false;
}
};
template <typename T>
inline bool test_negative(T n)
{
return is_negative<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_zero
{
static bool call(T n)
{
return (n == 0) ? true : false;
}
};
template <>
struct is_zero<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <>
struct is_zero<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <>
struct is_zero<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_ZERO;
}
};
template <typename T>
inline bool test_zero(T n)
{
return is_zero<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_nan
{
static bool call(T n)
{
// NaN numbers are not equal to anything
return (n != n) ? true : false;
}
};
template <>
struct is_nan<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <>
struct is_nan<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <>
struct is_nan<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_NAN;
}
};
template <typename T>
inline bool test_nan(T n)
{
return is_nan<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct is_infinite
{
static bool call(T n)
{
if (!std::numeric_limits<T>::has_infinity)
return false;
return (n == std::numeric_limits<T>::infinity()) ? true : false;
}
};
template <>
struct is_infinite<float>
{
static bool call(float n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <>
struct is_infinite<double>
{
static bool call(double n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <>
struct is_infinite<long double>
{
static bool call(long double n)
{
return (math::fpclassify)(n) == FP_INFINITE;
}
};
template <typename T>
inline bool test_infinite(T n)
{
return is_infinite<T>::call(n);
}
///////////////////////////////////////////////////////////////////////
struct cast_to_long
{
static long call(float n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
static long call(double n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
static long call(long double n, mpl::false_)
{
return static_cast<long>(std::floor(n));
}
template <typename T>
static long call(T n, mpl::false_)
{
// allow for ADL to find the correct overload for floor and
// lround
using namespace std;
return lround(floor(n));
}
template <typename T>
static long call(T n, mpl::true_)
{
return static_cast<long>(n);
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
struct truncate_to_long
{
static long call(float n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
static long call(double n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
static long call(long double n, mpl::false_)
{
return test_negative(n) ? static_cast<long>(std::ceil(n)) :
static_cast<long>(std::floor(n));
}
template <typename T>
static long call(T n, mpl::false_)
{
// allow for ADL to find the correct overloads for ltrunc
using namespace std;
return ltrunc(n);
}
template <typename T>
static long call(T n, mpl::true_)
{
return static_cast<long>(n);
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
//
// Traits class for radix specific number conversion
//
// Convert a digit from binary representation to character
// representation:
//
// static int call(unsigned n);
//
///////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename CharEncoding, typename Tag, bool radix_less_than_10>
struct convert_digit
{
static int call(unsigned n)
{
if (n <= 9)
return n + '0';
using spirit::char_class::convert;
return convert<CharEncoding>::to(Tag(), n - 10 + 'a');
}
};
template <>
struct convert_digit<unused_type, unused_type, false>
{
static int call(unsigned n)
{
if (n <= 9)
return n + '0';
return n - 10 + 'a';
}
};
template <typename CharEncoding, typename Tag>
struct convert_digit<CharEncoding, Tag, true>
{
static int call(unsigned n)
{
return n + '0';
}
};
}
template <unsigned Radix, typename CharEncoding, typename Tag>
struct convert_digit
: detail::convert_digit<CharEncoding, Tag, (Radix <= 10) ? true : false>
{};
///////////////////////////////////////////////////////////////////////
template <unsigned Radix>
struct divide
{
template <typename T>
static T call(T& n, mpl::true_)
{
return n / Radix;
}
template <typename T>
static T call(T& n, mpl::false_)
{
// Allow ADL to find the correct overload for floor
using namespace std;
return floor(n / Radix);
}
template <typename T>
static T call(T& n, T const&, int)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
template <typename T>
static T call(T& n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
// specialization for division by 10
template <>
struct divide<10>
{
template <typename T>
static T call(T& n, T, int, mpl::true_)
{
return n / 10;
}
template <typename T>
static T call(T, T& num, int exp, mpl::false_)
{
// Allow ADL to find the correct overload for floor
using namespace std;
return floor(num / spirit::traits::pow10<T>(exp));
}
template <typename T>
static T call(T& n, T& num, int exp)
{
return call(n, num, exp, mpl::bool_<is_integral<T>::value>());
}
template <typename T>
static T call(T& n)
{
return call(n, n, 1, mpl::bool_<is_integral<T>::value>());
}
};
///////////////////////////////////////////////////////////////////////
template <unsigned Radix>
struct remainder
{
template <typename T>
static long call(T n, mpl::true_)
{
// this cast is safe since we know the result is not larger
// than Radix
return static_cast<long>(n % Radix);
}
template <typename T>
static long call(T n, mpl::false_)
{
// Allow ADL to find the correct overload for fmod
using namespace std;
return cast_to_long::call(fmod(n, T(Radix)));
}
template <typename T>
static long call(T n)
{
return call(n, mpl::bool_<is_integral<T>::value>());
}
};
}}}
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The int_inserter template takes care of the integer to string
// conversion. If specified, the loop is unrolled for better performance.
//
// Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
// between 0 (no unrolling) and the largest expected generated integer
// string length (complete unrolling).
// If not specified, this value defaults to 6.
//
///////////////////////////////////////////////////////////////////////////
#define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data) \
if (!traits::test_zero(n)) { \
int ch = radix_type::call(remainder_type::call(n)); \
n = divide_type::call(n, num, ++exp); \
/**/
#define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data) \
*sink = char(ch); \
++sink; \
} \
/**/
template <
unsigned Radix, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct int_inserter
{
typedef traits::convert_digit<Radix, CharEncoding, Tag> radix_type;
typedef traits::divide<Radix> divide_type;
typedef traits::remainder<Radix> remainder_type;
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T n, T& num, int exp)
{
// remainder_type::call returns n % Radix
int ch = radix_type::call(remainder_type::call(n));
n = divide_type::call(n, num, ++exp);
BOOST_PP_REPEAT(
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
if (!traits::test_zero(n))
call(sink, n, num, exp);
BOOST_PP_REPEAT(
BOOST_KARMA_NUMERICS_LOOP_UNROLL,
BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _);
*sink = char(ch);
++sink;
return true;
}
// Common code for integer string representations
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T n)
{
return call(sink, n, n, 0);
}
private:
// helper function returning the biggest number representable either in
// a boost::long_long_type (if this does exist) or in a plain long
// otherwise
#if defined(BOOST_HAS_LONG_LONG)
typedef boost::long_long_type biggest_long_type;
#else
typedef long biggest_long_type;
#endif
static biggest_long_type max_long()
{
return (std::numeric_limits<biggest_long_type>::max)();
}
public:
// Specialization for doubles and floats, falling back to long integers
// for representable values. These specializations speed up formatting
// of floating point numbers considerably as all the required
// arithmetics will be executed using integral data types.
template <typename OutputIterator>
static bool
call(OutputIterator& sink, long double n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, double n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, float n)
{
if (std::fabs(n) < max_long())
{
biggest_long_type l((biggest_long_type)n);
return call(sink, l, l, 0);
}
return call(sink, n, n, 0);
}
};
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
#undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
///////////////////////////////////////////////////////////////////////////
//
// The uint_inserter template takes care of the conversion of any integer
// to a string, while interpreting the number as an unsigned type.
//
///////////////////////////////////////////////////////////////////////////
template <
unsigned Radix, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct uint_inserter : int_inserter<Radix, CharEncoding, Tag>
{
typedef int_inserter<Radix, CharEncoding, Tag> base_type;
// Common code for integer string representations
template <typename OutputIterator, typename T>
static bool
call(OutputIterator& sink, T const& n)
{
typedef typename traits::absolute_value<T>::type type;
type un = type(n);
return base_type::call(sink, un, un, 0);
}
};
///////////////////////////////////////////////////////////////////////////
//
// The sign_inserter template generates a sign for a given numeric value.
//
// The parameter forcesign allows to generate a sign even for positive
// numbers.
//
///////////////////////////////////////////////////////////////////////////
struct sign_inserter
{
template <typename OutputIterator>
static bool
call_noforce(OutputIterator& sink, bool is_zero, bool is_negative,
bool sign_if_zero)
{
// generate a sign for negative numbers only
if (is_negative || (is_zero && sign_if_zero)) {
*sink = '-';
++sink;
}
return true;
}
template <typename OutputIterator>
static bool
call_force(OutputIterator& sink, bool is_zero, bool is_negative,
bool sign_if_zero)
{
// generate a sign for all numbers except zero
if (!is_zero || sign_if_zero)
*sink = is_negative ? '-' : '+';
else
*sink = ' ';
++sink;
return true;
}
template <typename OutputIterator>
static bool
call(OutputIterator& sink, bool is_zero, bool is_negative
, bool forcesign, bool sign_if_zero = false)
{
return forcesign ?
call_force(sink, is_zero, is_negative, sign_if_zero) :
call_noforce(sink, is_zero, is_negative, sign_if_zero);
}
};
///////////////////////////////////////////////////////////////////////////
// These are helper functions for the real policies allowing to generate
// a single character and a string
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding = unused_type, typename Tag = unused_type>
struct char_inserter
{
template <typename OutputIterator, typename Char>
static bool call(OutputIterator& sink, Char c)
{
return detail::generate_to(sink, c, CharEncoding(), Tag());
}
};
template <typename CharEncoding = unused_type, typename Tag = unused_type>
struct string_inserter
{
template <typename OutputIterator, typename String>
static bool call(OutputIterator& sink, String str)
{
return detail::string_generate(sink, str, CharEncoding(), Tag());
}
};
}}}
#endif
@@ -0,0 +1,187 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM)
#define BOOST_SPIRIT_KARMA_REAL_UTILS_FEB_23_2007_0841PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/limits.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/detail/pow10.hpp>
#include <boost/spirit/home/support/detail/sign.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/spirit/home/karma/detail/string_generate.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// The real_inserter template takes care of the floating point number to
// string conversion. The Policies template parameter is used to allow
// customization of the formatting process
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_policies;
template <typename T
, typename Policies = real_policies<T>
, typename CharEncoding = unused_type
, typename Tag = unused_type>
struct real_inserter
{
template <typename OutputIterator, typename U>
static bool
call (OutputIterator& sink, U n, Policies const& p = Policies())
{
if (traits::test_nan(n)) {
return p.template nan<CharEncoding, Tag>(
sink, n, p.force_sign(n));
}
else if (traits::test_infinite(n)) {
return p.template inf<CharEncoding, Tag>(
sink, n, p.force_sign(n));
}
return p.template call<real_inserter>(sink, n, p);
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(push)
# pragma warning(disable: 4100) // 'p': unreferenced formal parameter
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4267) // conversion from 'size_t' to 'unsigned int', possible loss of data
#endif
///////////////////////////////////////////////////////////////////////
// This is the workhorse behind the real generator
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename U>
static bool
call_n (OutputIterator& sink, U n, Policies const& p)
{
// prepare sign and get output format
bool force_sign = p.force_sign(n);
bool sign_val = false;
int flags = p.floatfield(n);
if (traits::test_negative(n))
{
n = -n;
sign_val = true;
}
// The scientific representation requires the normalization of the
// value to convert.
// get correct precision for generated number
unsigned precision = p.precision(n);
if (std::numeric_limits<U>::digits10)
{
// limit generated precision to digits10, if defined
precision = (std::min)(precision,
(unsigned)std::numeric_limits<U>::digits10 + 1);
}
// allow for ADL to find the correct overloads for log10 et.al.
using namespace std;
U dim = 0;
if (0 == (Policies::fmtflags::fixed & flags) && !traits::test_zero(n))
{
dim = log10(n);
if (dim > 0)
n /= spirit::traits::pow10<U>(traits::truncate_to_long::call(dim));
else if (n < 1.) {
long exp = traits::truncate_to_long::call(-dim);
if (exp != -dim)
++exp;
dim = static_cast<U>(-exp);
n *= spirit::traits::pow10<U>(exp);
}
}
// prepare numbers (sign, integer and fraction part)
U integer_part;
U precexp = spirit::traits::pow10<U>(precision);
U fractional_part = modf(n, &integer_part);
fractional_part = floor(fractional_part * precexp + U(0.5));
if (fractional_part >= precexp)
{
fractional_part = floor(fractional_part - precexp);
integer_part += 1; // handle rounding overflow
}
// if trailing zeros are to be omitted, normalize the precision and
// fractional part
U long_int_part = floor(integer_part);
U long_frac_part = fractional_part;
unsigned prec = precision;
if (!p.trailing_zeros(n))
{
U frac_part_floor = long_frac_part;
if (0 != long_frac_part) {
// remove the trailing zeros
while (0 != prec &&
0 == traits::remainder<10>::call(long_frac_part))
{
long_frac_part = traits::divide<10>::call(long_frac_part);
--prec;
}
}
else {
// if the fractional part is zero, we don't need to output
// any additional digits
prec = 0;
}
if (precision != prec)
{
long_frac_part = frac_part_floor /
spirit::traits::pow10<U>(precision-prec);
}
}
// call the actual generating functions to output the different parts
if ((force_sign || sign_val) &&
traits::test_zero(long_int_part) &&
traits::test_zero(long_frac_part))
{
sign_val = false; // result is zero, no sign please
force_sign = false;
}
// generate integer part
bool r = p.integer_part(sink, long_int_part, sign_val, force_sign);
// generate decimal point
r = r && p.dot(sink, long_frac_part, precision);
// generate fractional part with the desired precision
r = r && p.fraction_part(sink, long_frac_part, prec, precision);
if (r && 0 == (Policies::fmtflags::fixed & flags)) {
return p.template exponent<CharEncoding, Tag>(sink,
traits::truncate_to_long::call(dim));
}
return r;
}
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
# pragma warning(pop)
#endif
};
}}}
#endif
@@ -0,0 +1,525 @@
// Copyright (c) 2001-2012 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_INT_FEB_23_2007_0840PM)
#define BOOST_SPIRIT_KARMA_INT_FEB_23_2007_0840PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
namespace tag
{
template <typename T, unsigned Radix, bool force_sign>
struct int_generator
{
BOOST_SPIRIT_IS_TAG()
};
}
namespace karma
{
///////////////////////////////////////////////////////////////////////
// This one is the class that the user can instantiate directly in
// order to create a customized int generator
template <typename T = int, unsigned Radix = 10, bool force_sign = false>
struct int_generator
: spirit::terminal<tag::int_generator<T, Radix, force_sign> >
{};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::short_> // enables short_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::int_> // enables int_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::long_> // enables long_
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, tag::long_long> // enables long_long
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, short> // enables lit(short(0))
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, int> // enables lit(0)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, long> // enables lit(0L)
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, boost::long_long_type> // enables lit(0LL)
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables short_(...)
, terminal_ex<tag::short_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables int_(...)
, terminal_ex<tag::int_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables long_(...)
, terminal_ex<tag::long_, fusion::vector1<A0> >
> : mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <typename A0>
struct use_terminal<karma::domain // enables long_long(...)
, terminal_ex<tag::long_long, fusion::vector1<A0> >
> : mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <> // enables *lazy* short_(...)
struct use_lazy_terminal<karma::domain, tag::short_, 1>
: mpl::true_ {};
template <> // enables *lazy* int_(...)
struct use_lazy_terminal<karma::domain, tag::int_, 1>
: mpl::true_ {};
template <> // enables *lazy* long_(...)
struct use_lazy_terminal<karma::domain, tag::long_, 1>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables *lazy* long_long(...)
struct use_lazy_terminal<karma::domain, tag::long_long, 1>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
// enables any custom int_generator
template <typename T, unsigned Radix, bool force_sign>
struct use_terminal<karma::domain, tag::int_generator<T, Radix, force_sign> >
: mpl::true_ {};
// enables any custom int_generator(...)
template <typename T, unsigned Radix, bool force_sign, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::int_generator<T, Radix, force_sign>
, fusion::vector1<A0> >
> : mpl::true_ {};
// enables *lazy* custom int_generator
template <typename T, unsigned Radix, bool force_sign>
struct use_lazy_terminal<
karma::domain
, tag::int_generator<T, Radix, force_sign>
, 1 // arity
> : mpl::true_ {};
// enables lit(int)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_int<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::short_;
using spirit::int_;
using spirit::long_;
#ifdef BOOST_HAS_LONG_LONG
using spirit::long_long;
#endif
using spirit::lit; // lit(1) is equivalent to 1
#endif
using spirit::short_type;
using spirit::int_type;
using spirit::long_type;
#ifdef BOOST_HAS_LONG_LONG
using spirit::long_long_type;
#endif
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for int generators not having a direct
// initializer: int_, long_ etc. These generators must be used in
// conjunction with an Attribute.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool force_sign>
struct any_int_generator
: primitive_generator<any_int_generator<T, CharEncoding, Tag, Radix
, force_sign> >
{
private:
template <typename OutputIterator, typename Attribute>
static bool insert_int(OutputIterator& sink, Attribute const& attr)
{
return sign_inserter::call(sink, traits::test_zero(attr)
, traits::test_negative(attr), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, traits::get_absolute_value(attr));
}
public:
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
signed_unsigned_mismatch, ());
// int has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr)
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return insert_int(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
// this int has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, int_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("integer");
}
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for int generators having a direct
// initializer: int_(10), long_(20) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool force_sign, bool no_attribute>
struct literal_int_generator
: primitive_generator<literal_int_generator<T, CharEncoding, Tag, Radix
, force_sign, no_attribute> >
{
private:
template <typename OutputIterator, typename Attribute>
static bool insert_int(OutputIterator& sink, Attribute const& attr)
{
return sign_inserter::call(sink, traits::test_zero(attr)
, traits::test_negative(attr), force_sign) &&
int_inserter<Radix, CharEncoding, Tag>::call(sink
, traits::get_absolute_value(attr));
}
public:
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_int_generator(typename add_const<T>::type n)
: n_(n) {}
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(std::numeric_limits<T>::is_signed,
signed_unsigned_mismatch, ());
// A int_(1) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
return insert_int(sink, n_) && delimit_out(sink, d);
}
// A int_(1) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return insert_int(sink, n_) && delimit_out(sink, d);
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("integer");
}
T n_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10
, bool force_sign = false>
struct make_int
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix
, force_sign
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::short_, Modifiers>
: detail::make_int<short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::int_, Modifiers>
: detail::make_int<int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::long_, Modifiers>
: detail::make_int<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<tag::long_long, Modifiers>
: detail::make_int<boost::long_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, bool force_sign, typename Modifiers>
struct make_primitive<tag::int_generator<T, Radix, force_sign>, Modifiers>
: detail::make_int<typename remove_const<T>::type
, Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10
, bool force_sign = false>
struct make_int_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix, force_sign, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::short_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<short, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::int_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<int, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_long, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<boost::long_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, bool force_sign, typename A0
, typename Modifiers>
struct make_primitive<
terminal_ex<tag::int_generator<T, Radix, force_sign>
, fusion::vector1<A0> >, Modifiers>
: detail::make_int_direct<typename remove_const<T>::type
, Modifiers, Radix, force_sign> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_int_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, false, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
template <typename Modifiers>
struct make_primitive<short, Modifiers>
: detail::basic_int_literal<short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<int, Modifiers>
: detail::basic_int_literal<int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<long, Modifiers>
: detail::basic_int_literal<long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<boost::long_long_type, Modifiers>
: detail::basic_int_literal<boost::long_long_type, Modifiers> {};
#endif
// lit(int)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_int<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_int_generator<
typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, false, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif
@@ -0,0 +1,454 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
#define BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/real_policies.hpp>
#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
namespace boost { namespace spirit
{
namespace karma
{
///////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename T>
struct real_policies;
///////////////////////////////////////////////////////////////////////
// This is the class that the user can instantiate directly in
// order to create a customized real generator
template <typename T = double, typename Policies = real_policies<T> >
struct real_generator
: spirit::terminal<tag::stateful_tag<Policies, tag::double_, T> >
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
real_generator() {}
real_generator(Policies const& p)
: spirit::terminal<tag_type>(p) {}
};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::float_> // enables float_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::double_> // enables double_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::long_double> // enables long_double
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, float> // enables lit(1.0f)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, double> // enables lit(1.0)
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, long double> // enables lit(1.0l)
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables float_(...)
, terminal_ex<tag::float_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables double_(...)
, terminal_ex<tag::double_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables long_double(...)
, terminal_ex<tag::long_double, fusion::vector1<A0> >
> : mpl::true_ {};
// lazy float_(...), double_(...), long_double(...)
template <>
struct use_lazy_terminal<karma::domain, tag::float_, 1>
: mpl::true_ {};
template <>
struct use_lazy_terminal<karma::domain, tag::double_, 1>
: mpl::true_ {};
template <>
struct use_lazy_terminal<karma::domain, tag::long_double, 1>
: mpl::true_ {};
///////////////////////////////////////////////////////////////////////////
// enables custom real generator
template <typename T, typename Policies>
struct use_terminal<karma::domain
, tag::stateful_tag<Policies, tag::double_, T> >
: mpl::true_ {};
template <typename T, typename Policies, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
, fusion::vector1<A0> > >
: mpl::true_ {};
// enables *lazy* custom real generator
template <typename T, typename Policies>
struct use_lazy_terminal<
karma::domain
, tag::stateful_tag<Policies, tag::double_, T>
, 1 // arity
> : mpl::true_ {};
// enables lit(double)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_real<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::float_;
using spirit::double_;
using spirit::long_double;
#endif
using spirit::float_type;
using spirit::double_type;
using spirit::long_double_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for real generators not having a direct
// initializer: float_, double_ etc. These generators must be used in
// conjunction with an attribute.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename Policies, typename CharEncoding, typename Tag>
struct any_real_generator
: primitive_generator<any_real_generator<T, Policies, CharEncoding, Tag> >
{
typedef typename Policies::properties properties;
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
any_real_generator(Policies const& policies = Policies())
: p_(policies) {}
// double_/float_/etc. has an attached attribute
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, traits::extract_from<T>(attr, context), p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// this double_/float_/etc. has no attribute attached, it needs to have
// been initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool generate(OutputIterator&, Context&, Delimiter const&
, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, real_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("real");
}
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for real generators having a direct
// initializer: float_(10.), double_(20.) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename Policies, typename CharEncoding, typename Tag
, bool no_attribute>
struct literal_real_generator
: primitive_generator<literal_real_generator<T, Policies, CharEncoding
, Tag, no_attribute> >
{
typedef typename Policies::properties properties;
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_real_generator(typename add_const<T>::type n
, Policies const& policies = Policies())
: n_(n), p_(policies) {}
// A double_(1.0) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, n_, p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
// A double_(1.0) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
typedef real_inserter<T, Policies, CharEncoding, Tag> inserter_type;
return inserter_type::call(sink, n_, p_) &&
karma::delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("real");
}
T n_;
Policies p_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers
, typename Policies = real_policies<T> >
struct make_real
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_real_generator<
T, Policies
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(get_stateful_data<tag_type>::call(term));
}
};
}
template <typename Modifiers>
struct make_primitive<tag::float_, Modifiers>
: detail::make_real<float, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::double_, Modifiers>
: detail::make_real<double, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::long_double, Modifiers>
: detail::make_real<long double, Modifiers> {};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Policies, typename Modifiers>
struct make_primitive<
tag::stateful_tag<Policies, tag::double_, T>, Modifiers>
: detail::make_real<typename remove_const<T>::type
, Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers
, typename Policies = real_policies<T> >
struct make_real_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
T, Policies
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
typedef tag::stateful_tag<Policies, tag::double_, T> tag_type;
using spirit::detail::get_stateful_data;
return result_type(T(fusion::at_c<0>(term.args))
, get_stateful_data<tag_type>::call(term.term));
}
};
}
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::float_, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<float, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::double_, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<double, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::long_double, fusion::vector1<A0> >, Modifiers>
: detail::make_real_direct<long double, Modifiers> {};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Policies, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::stateful_tag<Policies, tag::double_, T>
, fusion::vector1<A0> >
, Modifiers>
: detail::make_real_direct<typename remove_const<T>::type
, Modifiers, Policies> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_real_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
T, real_policies<T>
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(T(i));
}
};
}
template <typename Modifiers>
struct make_primitive<float, Modifiers>
: detail::basic_real_literal<float, Modifiers> {};
template <typename Modifiers>
struct make_primitive<double, Modifiers>
: detail::basic_real_literal<double, Modifiers> {};
template <typename Modifiers>
struct make_primitive<long double, Modifiers>
: detail::basic_real_literal<long double, Modifiers> {};
// lit(double)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_real<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_real_generator<
typename remove_const<A0>::type, real_policies<A0>
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif // defined(BOOST_SPIRIT_KARMA_REAL_FEB_26_2007_0512PM)
@@ -0,0 +1,334 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
#define BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/char.hpp>
#include <boost/spirit/home/karma/numeric/int.hpp>
#include <boost/spirit/home/karma/numeric/detail/real_utils.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
//
// real_policies, if you need special handling of your floating
// point numbers, just overload this policy class and use it as a template
// parameter to the karma::real_generator floating point specifier:
//
// template <typename T>
// struct scientific_policy : karma::real_policies<T>
// {
// // we want the numbers always to be in scientific format
// static int floatfield(T n) { return fmtflags::scientific; }
// };
//
// typedef
// karma::real_generator<double, scientific_policy<double> >
// science_type;
//
// karma::generate(sink, science_type(), 1.0); // will output: 1.0e00
//
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct real_policies
{
///////////////////////////////////////////////////////////////////////
// Expose the data type the generator is targeted at
///////////////////////////////////////////////////////////////////////
typedef T value_type;
///////////////////////////////////////////////////////////////////////
// By default the policy doesn't require any special iterator
// functionality. The floating point generator exposes its properties
// from here, so this needs to be updated in case other properties
// need to be implemented.
///////////////////////////////////////////////////////////////////////
typedef mpl::int_<generator_properties::no_properties> properties;
///////////////////////////////////////////////////////////////////////
// Specifies, which representation type to use during output
// generation.
///////////////////////////////////////////////////////////////////////
struct fmtflags
{
enum {
scientific = 0, // Generate floating-point values in scientific
// format (with an exponent field).
fixed = 1 // Generate floating-point values in fixed-point
// format (with no exponent field).
};
};
///////////////////////////////////////////////////////////////////////
// This is the main function used to generate the output for a
// floating point number. It is called by the real generator in order
// to perform the conversion. In theory all of the work can be
// implemented here, but it is the easiest to use existing
// functionality provided by the type specified by the template
// parameter `Inserter`.
//
// sink: the output iterator to use for generation
// n: the floating point number to convert
// p: the instance of the policy type used to instantiate this
// floating point generator.
///////////////////////////////////////////////////////////////////////
template <typename Inserter, typename OutputIterator, typename Policies>
static bool
call (OutputIterator& sink, T n, Policies const& p)
{
return Inserter::call_n(sink, n, p);
}
///////////////////////////////////////////////////////////////////////
// The default behavior is to not to require generating a sign. If
// 'force_sign()' returns true, then all generated numbers will
// have a sign ('+' or '-', zeros will have a space instead of a sign)
//
// n The floating point number to output. This can be used to
// adjust the required behavior depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static bool force_sign(T)
{
return false;
}
///////////////////////////////////////////////////////////////////////
// Return whether trailing zero digits have to be emitted in the
// fractional part of the output. If set, this flag instructs the
// floating point generator to emit trailing zeros up to the required
// precision digits (as returned by the precision() function).
//
// n The floating point number to output. This can be used to
// adjust the required behavior depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static bool trailing_zeros(T)
{
// the default behavior is not to generate trailing zeros
return false;
}
///////////////////////////////////////////////////////////////////////
// Decide, which representation type to use in the generated output.
//
// By default all numbers having an absolute value of zero or in
// between 0.001 and 100000 will be generated using the fixed format,
// all others will be generated using the scientific representation.
//
// The function trailing_zeros() can be used to force the output of
// trailing zeros in the fractional part up to the number of digits
// returned by the precision() member function. The default is not to
// generate the trailing zeros.
//
// n The floating point number to output. This can be used to
// adjust the formatting flags depending on the value of
// this number.
///////////////////////////////////////////////////////////////////////
static int floatfield(T n)
{
if (traits::test_zero(n))
return fmtflags::fixed;
T abs_n = traits::get_absolute_value(n);
return (abs_n >= 1e5 || abs_n < 1e-3)
? fmtflags::scientific : fmtflags::fixed;
}
///////////////////////////////////////////////////////////////////////
// Return the maximum number of decimal digits to generate in the
// fractional part of the output.
//
// n The floating point number to output. This can be used to
// adjust the required precision depending on the value of
// this number. If the trailing zeros flag is specified the
// fractional part of the output will be 'filled' with
// zeros, if appropriate
//
// Note: If the trailing_zeros flag is not in effect additional
// comments apply. See the comment for the fraction_part()
// function below. Moreover, this precision will be limited
// to the value of std::numeric_limits<T>::digits10 + 1
///////////////////////////////////////////////////////////////////////
static unsigned precision(T)
{
// by default, generate max. 3 fractional digits
return 3;
}
///////////////////////////////////////////////////////////////////////
// Generate the integer part of the number.
//
// sink The output iterator to use for generation
// n The absolute value of the integer part of the floating
// point number to convert (always non-negative).
// sign The sign of the overall floating point number to
// convert.
// force_sign Whether a sign has to be generated even for
// non-negative numbers. Note, that force_sign will be
// set to false for zero floating point values.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool integer_part (OutputIterator& sink, T n, bool sign
, bool force_sign)
{
return sign_inserter::call(
sink, traits::test_zero(n), sign, force_sign, force_sign) &&
int_inserter<10>::call(sink, n);
}
///////////////////////////////////////////////////////////////////////
// Generate the decimal point.
//
// sink The output iterator to use for generation
// n The fractional part of the floating point number to
// convert. Note that this number is scaled such, that
// it represents the number of units which correspond
// to the value returned from the precision() function
// earlier. I.e. a fractional part of 0.01234 is
// represented as 1234 when the 'Precision' is 5.
// precision The number of digits to emit as returned by the
// function 'precision()' above
//
// This is given to allow to decide, whether a decimal point
// has to be generated at all.
//
// Note: If the trailing_zeros flag is not in effect additional
// comments apply. See the comment for the fraction_part()
// function below.
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool dot (OutputIterator& sink, T /*n*/, unsigned /*precision*/)
{
return char_inserter<>::call(sink, '.'); // generate the dot by default
}
///////////////////////////////////////////////////////////////////////
// Generate the fractional part of the number.
//
// sink The output iterator to use for generation
// n The fractional part of the floating point number to
// convert. This number is scaled such, that it represents
// the number of units which correspond to the 'Precision'.
// I.e. a fractional part of 0.01234 is represented as 1234
// when the 'precision_' parameter is 5.
// precision_ The corrected number of digits to emit (see note
// below)
// precision The number of digits to emit as returned by the
// function 'precision()' above
//
// Note: If trailing_zeros() does not return true the 'precision_'
// parameter will have been corrected from the value the
// precision() function returned earlier (defining the maximal
// number of fractional digits) in the sense, that it takes into
// account trailing zeros. I.e. a floating point number 0.0123
// and a value of 5 returned from precision() will result in:
//
// trailing_zeros is not specified:
// n 123
// precision_ 4
//
// trailing_zeros is specified:
// n 1230
// precision_ 5
//
///////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
static bool fraction_part (OutputIterator& sink, T n
, unsigned precision_, unsigned precision)
{
// allow for ADL to find the correct overload for floor and log10
using namespace std;
// The following is equivalent to:
// generate(sink, right_align(precision, '0')[ulong], n);
// but it's spelled out to avoid inter-modular dependencies.
typename remove_const<T>::type digits =
(traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
bool r = true;
for (/**/; r && digits < precision_; digits = digits + 1)
r = char_inserter<>::call(sink, '0');
if (precision && r)
r = int_inserter<10>::call(sink, n);
return r;
}
///////////////////////////////////////////////////////////////////////
// Generate the exponential part of the number (this is called only
// if the floatfield() function returned the 'scientific' flag).
//
// sink The output iterator to use for generation
// n The (signed) exponential part of the floating point
// number to convert.
//
// The Tag template parameter is either of the type unused_type or
// describes the character class and conversion to be applied to any
// output possibly influenced by either the lower[...] or upper[...]
// directives.
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool exponent (OutputIterator& sink, long n)
{
long abs_n = traits::get_absolute_value(n);
bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
sign_inserter::call(sink, traits::test_zero(n)
, traits::test_negative(n), false);
// the C99 Standard requires at least two digits in the exponent
if (r && abs_n < 10)
r = char_inserter<CharEncoding, Tag>::call(sink, '0');
return r && int_inserter<10>::call(sink, abs_n);
}
///////////////////////////////////////////////////////////////////////
// Print the textual representations for non-normal floats (NaN and
// Inf)
//
// sink The output iterator to use for generation
// n The (signed) floating point number to convert.
// force_sign Whether a sign has to be generated even for
// non-negative numbers
//
// The Tag template parameter is either of the type unused_type or
// describes the character class and conversion to be applied to any
// output possibly influenced by either the lower[...] or upper[...]
// directives.
//
// Note: These functions get called only if fpclassify() returned
// FP_INFINITY or FP_NAN.
///////////////////////////////////////////////////////////////////////
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool nan (OutputIterator& sink, T n, bool force_sign)
{
return sign_inserter::call(
sink, false, traits::test_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "nan");
}
template <typename CharEncoding, typename Tag, typename OutputIterator>
static bool inf (OutputIterator& sink, T n, bool force_sign)
{
return sign_inserter::call(
sink, false, traits::test_negative(n), force_sign) &&
string_inserter<CharEncoding, Tag>::call(sink, "inf");
}
};
}}}
#endif // defined(BOOST_SPIRIT_KARMA_REAL_POLICIES_MAR_02_2007_0936AM)
@@ -0,0 +1,576 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM)
#define BOOST_SPIRIT_KARMA_UINT_FEB_23_2007_0840PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/numeric_traits.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/detail/get_encoding.hpp>
#include <boost/spirit/home/support/detail/is_spirit_tag.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/spirit/home/karma/detail/get_casetag.hpp>
#include <boost/spirit/home/karma/detail/extract_from.hpp>
#include <boost/spirit/home/karma/detail/enable_lit.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/numeric/detail/numeric_utils.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/fusion/include/vector.hpp>
namespace boost { namespace spirit
{
namespace tag
{
template <typename T, unsigned Radix>
struct uint_generator
{
BOOST_SPIRIT_IS_TAG()
};
}
namespace karma
{
///////////////////////////////////////////////////////////////////////
// This one is the class that the user can instantiate directly in
// order to create a customized int generator
template <typename T = unsigned int, unsigned Radix = 10>
struct uint_generator
: spirit::terminal<tag::uint_generator<T, Radix> >
{};
}
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_terminal<karma::domain, tag::ushort_> // enables ushort_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::uint_> // enables uint_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::ulong_> // enables ulong_
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::bin> // enables bin
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::oct> // enables oct
: mpl::true_ {};
template <>
struct use_terminal<karma::domain, tag::hex> // enables hex
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <>
struct use_terminal<karma::domain, tag::ulong_long> // enables ulong_long
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <> // enables lit(unsigned short(0))
struct use_terminal<karma::domain, unsigned short>
: mpl::true_ {};
#endif
template <> // enables lit(0U)
struct use_terminal<karma::domain, unsigned int>
: mpl::true_ {};
template <> // enables lit(0UL)
struct use_terminal<karma::domain, unsigned long>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables lit(0ULL)
struct use_terminal<karma::domain, boost::ulong_long_type>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <typename A0>
struct use_terminal<karma::domain // enables ushort_(...)
, terminal_ex<tag::ushort_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables uint_(...)
, terminal_ex<tag::uint_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables ulong_(...)
, terminal_ex<tag::ulong_, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables bin(...)
, terminal_ex<tag::bin, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables oct(...)
, terminal_ex<tag::oct, fusion::vector1<A0> >
> : mpl::true_ {};
template <typename A0>
struct use_terminal<karma::domain // enables hex(...)
, terminal_ex<tag::hex, fusion::vector1<A0> >
> : mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <typename A0>
struct use_terminal<karma::domain // enables ulong_long(...)
, terminal_ex<tag::ulong_long, fusion::vector1<A0> >
> : mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
template <> // enables *lazy* ushort_(...)
struct use_lazy_terminal<karma::domain, tag::ushort_, 1>
: mpl::true_ {};
template <> // enables *lazy* uint_(...)
struct use_lazy_terminal<karma::domain, tag::uint_, 1>
: mpl::true_ {};
template <> // enables *lazy* ulong_(...)
struct use_lazy_terminal<karma::domain, tag::ulong_, 1>
: mpl::true_ {};
template <> // enables *lazy* bin(...)
struct use_lazy_terminal<karma::domain, tag::bin, 1>
: mpl::true_ {};
template <> // enables *lazy* oct(...)
struct use_lazy_terminal<karma::domain, tag::oct, 1>
: mpl::true_ {};
template <> // enables *lazy* hex(...)
struct use_lazy_terminal<karma::domain, tag::hex, 1>
: mpl::true_ {};
#ifdef BOOST_HAS_LONG_LONG
template <> // enables *lazy* ulong_long(...)
struct use_lazy_terminal<karma::domain, tag::ulong_long, 1>
: mpl::true_ {};
#endif
///////////////////////////////////////////////////////////////////////////
// enables any custom uint_generator
template <typename T, unsigned Radix>
struct use_terminal<karma::domain, tag::uint_generator<T, Radix> >
: mpl::true_ {};
// enables any custom uint_generator(...)
template <typename T, unsigned Radix, typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
> : mpl::true_ {};
// enables *lazy* custom uint_generator
template <typename T, unsigned Radix>
struct use_lazy_terminal<
karma::domain
, tag::uint_generator<T, Radix>
, 1 // arity
> : mpl::true_ {};
// enables lit(uint)
template <typename A0>
struct use_terminal<karma::domain
, terminal_ex<tag::lit, fusion::vector1<A0> >
, typename enable_if<traits::is_uint<A0> >::type>
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::ushort_;
using spirit::uint_;
using spirit::ulong_;
#ifdef BOOST_HAS_LONG_LONG
using spirit::ulong_long;
#endif
using spirit::bin;
using spirit::oct;
using spirit::hex;
using spirit::lit; // lit(1U) is equivalent to 1U
#endif
using spirit::ushort_type;
using spirit::uint_type;
using spirit::ulong_type;
#ifdef BOOST_HAS_LONG_LONG
using spirit::ulong_long_type;
#endif
using spirit::bin_type;
using spirit::oct_type;
using spirit::hex_type;
using spirit::lit_type;
///////////////////////////////////////////////////////////////////////////
// This specialization is used for unsigned int generators not having a
// direct initializer: uint_, ulong_ etc. These generators must be used in
// conjunction with an Attribute.
///////////////////////////////////////////////////////////////////////////
template <typename T, typename CharEncoding, typename Tag, unsigned Radix>
struct any_uint_generator
: primitive_generator<any_uint_generator<T, CharEncoding, Tag, Radix> >
{
template <typename Context, typename Unused>
struct attribute
{
typedef T type;
};
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix >= 2 && Radix <= 36, not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(
// the following is a workaround for STLPort, where the simpler
// `!std::numeric_limits<T>::is_signed` wouldn't compile
mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
signed_unsigned_mismatch, ());
// int has a Attribute attached
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
static bool
generate(OutputIterator& sink, Context& context, Delimiter const& d
, Attribute const& attr)
{
if (!traits::has_optional_value(attr))
return false; // fail if it's an uninitialized optional
return uint_inserter<Radix, CharEncoding, Tag>::
call(sink, traits::extract_from<T>(attr, context)) &&
delimit_out(sink, d); // always do post-delimiting
}
// this int has no Attribute attached, it needs to have been
// initialized from a direct literal
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
generate(OutputIterator&, Context&, Delimiter const&, unused_type)
{
// It is not possible (doesn't make sense) to use numeric generators
// without providing any attribute, as the generator doesn't 'know'
// what to output. The following assertion fires if this situation
// is detected in your code.
BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, uint_not_usable_without_attribute, ());
return false;
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("unsigned-integer");
}
};
///////////////////////////////////////////////////////////////////////////
// This specialization is used for unsigned int generators having a direct
// initializer: uint_(10), ulong_(20) etc.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename CharEncoding, typename Tag, unsigned Radix
, bool no_attribute>
struct literal_uint_generator
: primitive_generator<literal_uint_generator<T, CharEncoding, Tag, Radix
, no_attribute> >
{
template <typename Context, typename Unused = unused_type>
struct attribute
: mpl::if_c<no_attribute, unused_type, T>
{};
literal_uint_generator(typename add_const<T>::type n)
: n_(n) {}
// check template Attribute 'Radix' for validity
BOOST_SPIRIT_ASSERT_MSG(
Radix >= 2 && Radix <= 36, not_supported_radix, ());
BOOST_SPIRIT_ASSERT_MSG(
// the following is a workaround for STLPort, where the simpler
// `!std::numeric_limits<T>::is_signed wouldn't` compile
mpl::not_<mpl::bool_<std::numeric_limits<T>::is_signed> >::value,
signed_unsigned_mismatch, ());
// A uint(1U) which additionally has an associated attribute emits
// its immediate literal only if it matches the attribute, otherwise
// it fails.
template <typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& d, Attribute const& attr) const
{
typedef typename attribute<Context>::type attribute_type;
if (!traits::has_optional_value(attr) ||
n_ != traits::extract_from<attribute_type>(attr, context))
{
return false;
}
return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
delimit_out(sink, d); // always do post-delimiting
}
// A uint(1U) without any associated attribute just emits its
// immediate literal
template <typename OutputIterator, typename Context, typename Delimiter>
bool generate(OutputIterator& sink, Context&, Delimiter const& d
, unused_type) const
{
return uint_inserter<Radix, CharEncoding, Tag>::call(sink, n_) &&
delimit_out(sink, d); // always do post-delimiting
}
template <typename Context>
static info what(Context const& /*context*/)
{
return info("unsigned-integer");
}
T n_;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10>
struct make_uint
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef any_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix
> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type();
}
};
}
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::ushort_, Modifiers>
: detail::make_uint<unsigned short, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::uint_, Modifiers>
: detail::make_uint<unsigned int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::ulong_, Modifiers>
: detail::make_uint<unsigned long, Modifiers> {};
template <typename Modifiers>
struct make_primitive<tag::bin, Modifiers>
: detail::make_uint<unsigned, Modifiers, 2> {};
template <typename Modifiers>
struct make_primitive<tag::oct, Modifiers>
: detail::make_uint<unsigned, Modifiers, 8> {};
template <typename Modifiers>
struct make_primitive<tag::hex, Modifiers>
: detail::make_uint<unsigned, Modifiers, 16> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<tag::ulong_long, Modifiers>
: detail::make_uint<boost::ulong_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, typename Modifiers>
struct make_primitive<tag::uint_generator<T, Radix>, Modifiers>
: detail::make_uint<typename remove_const<T>::type, Modifiers, Radix> {};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers, unsigned Radix = 10>
struct make_uint_direct
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, Radix, false
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ushort_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned short, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::uint_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned int, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ulong_, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned long, Modifiers> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::bin, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 2> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::oct, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 8> {};
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::hex, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<unsigned, Modifiers, 16> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::ulong_long, fusion::vector1<A0> >, Modifiers>
: detail::make_uint_direct<boost::ulong_long_type, Modifiers> {};
#endif
template <typename T, unsigned Radix, typename A0, typename Modifiers>
struct make_primitive<
terminal_ex<tag::uint_generator<T, Radix>, fusion::vector1<A0> >
, Modifiers>
: detail::make_uint_direct<typename remove_const<T>::type, Modifiers, Radix>
{};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T, typename Modifiers>
struct basic_uint_literal
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
T
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, true
> result_type;
template <typename T_>
result_type operator()(T_ i, unused_type) const
{
return result_type(i);
}
};
}
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template <typename Modifiers>
struct make_primitive<unsigned short, Modifiers>
: detail::basic_uint_literal<unsigned short, Modifiers> {};
#endif
template <typename Modifiers>
struct make_primitive<unsigned int, Modifiers>
: detail::basic_uint_literal<unsigned int, Modifiers> {};
template <typename Modifiers>
struct make_primitive<unsigned long, Modifiers>
: detail::basic_uint_literal<unsigned long, Modifiers> {};
#ifdef BOOST_HAS_LONG_LONG
template <typename Modifiers>
struct make_primitive<boost::ulong_long_type, Modifiers>
: detail::basic_uint_literal<boost::ulong_long_type, Modifiers> {};
#endif
// lit(uint)
template <typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<tag::lit, fusion::vector1<A0> >
, Modifiers
, typename enable_if<traits::is_uint<A0> >::type>
{
static bool const lower =
has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
static bool const upper =
has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
typedef literal_uint_generator<
typename remove_const<A0>::type
, typename spirit::detail::get_encoding_with_case<
Modifiers, unused_type, lower || upper>::type
, typename detail::get_casetag<Modifiers, lower || upper>::type
, 10, true
> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
#endif
@@ -0,0 +1,22 @@
// 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_OPERATOR_FEB_28_2007_0351PM)
#define BOOST_SPIRIT_KARMA_OPERATOR_FEB_28_2007_0351PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/operator/sequence.hpp>
#include <boost/spirit/home/karma/operator/and_predicate.hpp>
#include <boost/spirit/home/karma/operator/not_predicate.hpp>
#include <boost/spirit/home/karma/operator/alternative.hpp>
#include <boost/spirit/home/karma/operator/kleene.hpp>
#include <boost/spirit/home/karma/operator/plus.hpp>
#include <boost/spirit/home/karma/operator/optional.hpp>
#include <boost/spirit/home/karma/operator/list.hpp>
#endif
@@ -0,0 +1,208 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM)
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1117AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/detail/alternative_function.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/detail/what_function.hpp>
#include <boost/fusion/include/any.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/mpl/bitor.hpp>
#include <boost/config.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::bitwise_or> // enables |
: mpl::true_ {};
template <>
struct flatten_tree<karma::domain, proto::tag::bitwise_or> // flattens |
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
// specialization for sequences
template <typename Elements>
struct alternative_properties
{
struct element_properties
{
template <typename T>
struct result;
template <typename F, typename Element>
struct result<F(Element)>
{
typedef properties_of<Element> type;
};
// never called, but needed for decltype-based result_of (C++0x)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Element>
typename result<element_properties(Element)>::type
operator()(Element&&) const;
#endif
};
typedef typename mpl::accumulate<
typename fusion::result_of::transform<
Elements, element_properties>::type
, mpl::int_<karma::generator_properties::countingbuffer>
, mpl::bitor_<mpl::_2, mpl::_1>
>::type type;
};
}}}
namespace boost { namespace spirit { namespace karma
{
template <typename Elements, typename Strict, typename Derived>
struct base_alternative : nary_generator<Derived>
{
typedef typename traits::alternative_properties<Elements>::type
properties;
template <typename Context, typename Iterator = unused_type>
struct attribute
{
// Put all the element attributes in a tuple
typedef typename traits::build_attribute_sequence<
Elements, Context, traits::alternative_attribute_transform
, Iterator, karma::domain
>::type all_attributes;
// Ok, now make a variant over the attribute sequence. Note that
// build_variant makes sure that 1) all attributes in the variant
// are unique 2) puts the unused attribute, if there is any, to
// the front and 3) collapses single element variants, variant<T>
// to T.
typedef typename traits::build_variant<all_attributes>::type type;
};
base_alternative(Elements const& elements)
: elements(elements) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
typedef detail::alternative_generate_function<
OutputIterator, Context, Delimiter, Attribute, Strict
> functor;
// f return true if *any* of the parser succeeds
functor f (sink, ctx, d, attr);
return fusion::any(elements, f);
}
template <typename Context>
info what(Context& context) const
{
info result("alternative");
fusion::for_each(elements,
spirit::detail::what_function<Context>(result, context));
return result;
}
Elements elements;
};
template <typename Elements>
struct alternative
: base_alternative<Elements, mpl::false_, alternative<Elements> >
{
typedef base_alternative<Elements, mpl::false_, alternative>
base_alternative_;
alternative(Elements const& elements)
: base_alternative_(elements) {}
};
template <typename Elements>
struct strict_alternative
: base_alternative<Elements, mpl::true_, strict_alternative<Elements> >
{
typedef base_alternative<Elements, mpl::true_, strict_alternative>
base_alternative_;
strict_alternative(Elements const& elements)
: base_alternative_(elements) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Elements, bool strict_mode = false>
struct make_alternative
: make_nary_composite<Elements, alternative>
{};
template <typename Elements>
struct make_alternative<Elements, true>
: make_nary_composite<Elements, strict_alternative>
{};
}
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::bitwise_or, Elements, Modifiers>
: detail::make_alternative<Elements
, detail::get_stricttag<Modifiers>::value>
{};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Elements>
struct has_semantic_action<karma::alternative<Elements> >
: nary_has_semantic_action<Elements> {};
template <typename Elements>
struct has_semantic_action<karma::strict_alternative<Elements> >
: nary_has_semantic_action<Elements> {};
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::alternative<Elements>
, Attribute, Context, Iterator>
: nary_handles_container<Elements, Attribute, Context, Iterator> {};
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_alternative<Elements>
, Attribute, Context, Iterator>
: nary_handles_container<Elements, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,95 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_AND_PREDICATE_MAR_22_2009_0412PM)
#define SPIRIT_KARMA_AND_PREDICATE_MAR_22_2009_0412PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::address_of> // enables &g
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
template <typename Subject>
struct and_predicate : unary_generator<and_predicate<Subject> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::disabling | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
and_predicate(Subject const& subject)
: subject(subject) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// inhibits output
detail::disable_output<OutputIterator> disable(sink);
return subject.generate(sink, ctx, d, attr);
}
template <typename Context>
info what(Context& context) const
{
return info("and-predicate", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::address_of, Elements, Modifiers>
: make_unary_composite<Elements, and_predicate> {};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::and_predicate<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::and_predicate<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,208 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_KLEENE_MAR_03_2007_0337AM)
#define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/detail/pass_container.hpp>
#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/type_traits/add_const.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::dereference> // enables *g
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Subject, typename Strict, typename Derived>
struct base_kleene : unary_generator<Derived>
{
private:
// Ignore return value in relaxed mode (failing subject generators
// are just skipped). This allows to selectively generate items in
// the provided attribute.
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, mpl::false_) const
{
bool r = !f(subject);
if (!r && !f.is_at_end())
f.next();
return true;
}
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, mpl::true_) const
{
return !f(subject);
}
// There is no way to distinguish a failed generator from a
// generator to be skipped. We assume the user takes responsibility
// for ending the loop if no attribute is specified.
template <typename F>
bool generate_subject(F f, unused_type, mpl::false_) const
{
return !f(subject);
}
// template <typename F>
// bool generate_subject(F f, unused_type, mpl::true_) const
// {
// return !f(subject);
// }
public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
// Build a std::vector from the subject's attribute. Note
// that build_std_vector may return unused_type if the
// subject's attribute is an unused_type.
template <typename Context, typename Iterator>
struct attribute
: traits::build_std_vector<
typename traits::attribute_of<Subject, Context, Iterator>::type
>
{};
base_kleene(Subject const& subject)
: subject(subject) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
typedef detail::fail_function<
OutputIterator, Context, Delimiter> fail_function;
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
typedef
typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
fail_function, Attribute, indirect_iterator_type, mpl::false_>
pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(it), indirect_iterator_type(end));
// kleene fails only if the underlying output fails
while (!pass.is_at_end())
{
if (!generate_subject(pass, attr, Strict()))
break;
}
return detail::sink_is_good(sink);
}
template <typename Context>
info what(Context& context) const
{
return info("kleene", subject.what(context));
}
Subject subject;
};
template <typename Subject>
struct kleene
: base_kleene<Subject, mpl::false_, kleene<Subject> >
{
typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
kleene(Subject const& subject)
: base_kleene_(subject) {}
};
template <typename Subject>
struct strict_kleene
: base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
{
typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
strict_kleene(Subject const& subject)
: base_kleene_(subject) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Subject, bool strict_mode = false>
struct make_kleene
: make_unary_composite<Subject, kleene>
{};
template <typename Subject>
struct make_kleene<Subject, true>
: make_unary_composite<Subject, strict_kleene>
{};
}
template <typename Subject, typename Modifiers>
struct make_composite<proto::tag::dereference, Subject, Modifiers>
: detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
{};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::kleene<Subject> >
: unary_has_semantic_action<Subject> {};
template <typename Subject>
struct has_semantic_action<karma::strict_kleene<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::kleene<Subject>, Attribute
, Context, Iterator>
: mpl::true_ {};
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_kleene<Subject>, Attribute
, Context, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,229 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_LIST_MAY_01_2007_0229PM)
#define SPIRIT_KARMA_LIST_MAY_01_2007_0229PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/detail/pass_container.hpp>
#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::modulus> // enables g % d
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Left, typename Right, typename Strict, typename Derived>
struct base_list : binary_generator<Derived>
{
private:
// iterate over the given container until its exhausted or the embedded
// (left) generator succeeds
template <typename F, typename Attribute>
bool generate_left(F f, Attribute const&, mpl::false_) const
{
// Failing subject generators are just skipped. This allows to
// selectively generate items in the provided attribute.
while (!f.is_at_end())
{
bool r = !f(left);
if (r)
return true;
if (!f.is_at_end())
f.next();
}
return false;
}
template <typename F, typename Attribute>
bool generate_left(F f, Attribute const&, mpl::true_) const
{
return !f(left);
}
// There is no way to distinguish a failed generator from a
// generator to be skipped. We assume the user takes responsibility
// for ending the loop if no attribute is specified.
template <typename F>
bool generate_left(F f, unused_type, mpl::false_) const
{
return !f(left);
}
public:
typedef Left left_type;
typedef Right right_type;
typedef mpl::int_<
left_type::properties::value
| right_type::properties::value
| generator_properties::buffering
| generator_properties::counting
> properties;
// Build a std::vector from the LHS's attribute. Note
// that build_std_vector may return unused_type if the
// subject's attribute is an unused_type.
template <typename Context, typename Iterator>
struct attribute
: traits::build_std_vector<
typename traits::attribute_of<Left, Context, Iterator>::type>
{};
base_list(Left const& left, Right const& right)
: left(left), right(right)
{}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
typedef detail::fail_function<
OutputIterator, Context, Delimiter
> fail_function;
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
typedef
typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
fail_function, Attribute, indirect_iterator_type, mpl::false_>
pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(it), indirect_iterator_type(end));
if (generate_left(pass, attr, Strict()))
{
while (!pass.is_at_end())
{
// wrap the given output iterator as generate_left might fail
detail::enable_buffering<OutputIterator> buffering(sink);
{
detail::disable_counting<OutputIterator> nocounting(sink);
if (!right.generate(sink, ctx, d, unused))
return false; // shouldn't happen
if (!generate_left(pass, attr, Strict()))
break; // return true as one item succeeded
}
buffering.buffer_copy();
}
return detail::sink_is_good(sink);
}
return false;
}
template <typename Context>
info what(Context& context) const
{
return info("list",
std::make_pair(left.what(context), right.what(context)));
}
Left left;
Right right;
};
template <typename Left, typename Right>
struct list
: base_list<Left, Right, mpl::false_, list<Left, Right> >
{
typedef base_list<Left, Right, mpl::false_, list> base_list_;
list(Left const& left, Right const& right)
: base_list_(left, right) {}
};
template <typename Left, typename Right>
struct strict_list
: base_list<Left, Right, mpl::true_, strict_list<Left, Right> >
{
typedef base_list<Left, Right, mpl::true_, strict_list> base_list_;
strict_list (Left const& left, Right const& right)
: base_list_(left, right) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Subject, bool strict_mode = false>
struct make_list
: make_binary_composite<Subject, list>
{};
template <typename Subject>
struct make_list<Subject, true>
: make_binary_composite<Subject, strict_list>
{};
}
template <typename Subject, typename Modifiers>
struct make_composite<proto::tag::modulus, Subject, Modifiers>
: detail::make_list<Subject, detail::get_stricttag<Modifiers>::value>
{};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Left, typename Right>
struct has_semantic_action<karma::list<Left, Right> >
: binary_has_semantic_action<Left, Right> {};
template <typename Left, typename Right>
struct has_semantic_action<karma::strict_list<Left, Right> >
: binary_has_semantic_action<Left, Right> {};
///////////////////////////////////////////////////////////////////////////
template <typename Left, typename Right, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::list<Left, Right>, Attribute
, Context, Iterator>
: mpl::true_ {};
template <typename Left, typename Right, typename Attribute
, typename Context, typename Iterator>
struct handles_container<karma::strict_list<Left, Right>, Attribute
, Context, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,96 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_NOT_PREDICATE_MAR_21_2009_1132AM)
#define SPIRIT_KARMA_NOT_PREDICATE_MAR_21_2009_1132AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::logical_not> // enables !g
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace karma
{
template <typename Subject>
struct not_predicate : unary_generator<not_predicate<Subject> >
{
typedef Subject subject_type;
typedef mpl::int_<
generator_properties::disabling | subject_type::properties::value
> properties;
template <typename Context, typename Iterator>
struct attribute
: traits::attribute_of<subject_type, Context, Iterator>
{};
not_predicate(Subject const& subject)
: subject(subject) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
// inhibits output
detail::disable_output<OutputIterator> disable(sink);
return !subject.generate(sink, ctx, d, attr);
}
template <typename Context>
info what(Context& context) const
{
return info("not-predicate", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::logical_not, Elements, Modifiers>
: make_unary_composite<Elements, not_predicate> {};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::not_predicate<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::not_predicate<Subject>, Attribute
, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,105 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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(SPIRIT_KARMA_OPTIONAL_MARCH_31_2007_0852AM)
#define SPIRIT_KARMA_OPTIONAL_MARCH_31_2007_0852AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/optional.hpp>
#include <boost/type_traits/is_convertible.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::negate> // enables -g
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct optional : unary_generator<optional<Subject> >
{
typedef Subject subject_type;
typedef typename subject_type::properties properties;
// Build a boost::optional from the subject's attribute. Note
// that boost::optional may return unused_type if the
// subject's attribute is an unused_type.
template <typename Context, typename Iterator = unused_type>
struct attribute
: traits::build_optional<
typename traits::attribute_of<Subject, Context, Iterator>::type
>
{};
optional(Subject const& subject)
: subject(subject) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
if (traits::has_optional_value(attr))
subject.generate(sink, ctx, d, traits::optional_value(attr));
return sink_is_good(sink);
}
template <typename Context>
info what(Context& context) const
{
return info("optional", subject.what(context));
}
Subject subject;
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::negate, Elements, Modifiers>
: make_unary_composite<Elements, optional> {};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::optional<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::optional<Subject>, Attribute, Context
, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,226 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_POSITIVE_MAR_03_2007_0945PM)
#define BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/karma/detail/pass_container.hpp>
#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/type_traits/add_const.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::unary_plus> // enables +g
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Subject, typename Strict, typename Derived>
struct base_plus : unary_generator<Derived>
{
private:
// Ignore return value in relaxed mode (failing subject generators
// are just skipped). This allows to selectively generate items in
// the provided attribute.
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, bool& result, mpl::false_) const
{
bool r = !f(subject);
if (r)
result = true;
else if (!f.is_at_end())
f.next();
return true;
}
template <typename F, typename Attribute>
bool generate_subject(F f, Attribute const&, bool& result, mpl::true_) const
{
bool r = !f(subject);
if (r)
result = true;
return r;
}
// There is no way to distinguish a failed generator from a
// generator to be skipped. We assume the user takes responsibility
// for ending the loop if no attribute is specified.
template <typename F>
bool generate_subject(F f, unused_type, bool& result, mpl::false_) const
{
bool r = f(subject);
if (!r)
result = true;
return !r;
}
// template <typename F>
// bool generate_subject(F f, unused_type, bool& result, mpl::true_) const
// {
// bool r = f(subject);
// if (!r)
// result = true;
// return !r;
// }
public:
typedef Subject subject_type;
typedef typename subject_type::properties properties;
// Build a std::vector from the subjects attribute. Note
// that build_std_vector may return unused_type if the
// subject's attribute is an unused_type.
template <typename Context, typename Iterator>
struct attribute
: traits::build_std_vector<
typename traits::attribute_of<subject_type, Context, Iterator>::type
>
{};
base_plus(Subject const& subject)
: subject(subject) {}
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr) const
{
typedef detail::fail_function<
OutputIterator, Context, Delimiter> fail_function;
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
typedef
typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
fail_function, Attribute, indirect_iterator_type, mpl::false_>
pass_container;
iterator_type it = traits::begin(attr);
iterator_type end = traits::end(attr);
// plus fails if the parameter is empty
if (traits::compare(it, end))
return false;
pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(it), indirect_iterator_type(end));
// from now on plus fails if the underlying output fails or overall
// no subject generators succeeded
bool result = false;
while (!pass.is_at_end())
{
if (!generate_subject(pass, attr, result, Strict()))
break;
}
return result && detail::sink_is_good(sink);
}
template <typename Context>
info what(Context& context) const
{
return info("plus", subject.what(context));
}
Subject subject;
};
template <typename Subject>
struct plus
: base_plus<Subject, mpl::false_, plus<Subject> >
{
typedef base_plus<Subject, mpl::false_, plus> base_plus_;
plus(Subject const& subject)
: base_plus_(subject) {}
};
template <typename Subject>
struct strict_plus
: base_plus<Subject, mpl::true_, strict_plus<Subject> >
{
typedef base_plus<Subject, mpl::true_, strict_plus> base_plus_;
strict_plus(Subject const& subject)
: base_plus_(subject) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Elements, bool strict_mode = false>
struct make_plus
: make_unary_composite<Elements, plus>
{};
template <typename Elements>
struct make_plus<Elements, true>
: make_unary_composite<Elements, strict_plus>
{};
}
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::unary_plus, Elements, Modifiers>
: detail::make_plus<Elements, detail::get_stricttag<Modifiers>::value>
{};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct has_semantic_action<karma::plus<Subject> >
: unary_has_semantic_action<Subject> {};
template <typename Subject>
struct has_semantic_action<karma::strict_plus<Subject> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::plus<Subject>, Attribute
, Context, Iterator>
: mpl::true_ {};
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_plus<Subject>, Attribute
, Context, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,313 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0247PM)
#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0247PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/detail/fail_function.hpp>
#include <boost/spirit/home/karma/detail/pass_container.hpp>
#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/detail/what_function.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/support/algorithm/any_if.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/sequence_base_id.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/attributes.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/bitor.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/fusion/include/transform.hpp>
#include <boost/mpl/accumulate.hpp>
#include <boost/config.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<karma::domain, proto::tag::shift_left> // enables <<
: mpl::true_ {};
template <>
struct flatten_tree<karma::domain, proto::tag::shift_left> // flattens <<
: mpl::true_ {};
}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
// specialization for sequences
template <typename Elements>
struct sequence_properties
{
struct element_properties
{
template <typename T>
struct result;
template <typename F, typename Element>
struct result<F(Element)>
{
typedef properties_of<Element> type;
};
// never called, but needed for decltype-based result_of (C++0x)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Element>
typename result<element_properties(Element)>::type
operator()(Element&&) const;
#endif
};
typedef typename mpl::accumulate<
typename fusion::result_of::transform<
Elements, element_properties>::type
, mpl::int_<karma::generator_properties::no_properties>
, mpl::bitor_<mpl::_2, mpl::_1>
>::type type;
};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Elements, typename Strict, typename Derived>
struct base_sequence : nary_generator<Derived>
{
typedef typename traits::sequence_properties<Elements>::type properties;
base_sequence(Elements const& elements)
: elements(elements) {}
typedef Elements elements_type;
struct sequence_base_id;
template <typename Context, typename Iterator = unused_type>
struct attribute
{
// Put all the element attributes in a tuple
typedef typename traits::build_attribute_sequence<
Elements, Context, traits::sequence_attribute_transform
, Iterator, karma::domain
>::type all_attributes;
// Now, build a fusion vector over the attributes. Note
// that build_fusion_vector 1) removes all unused attributes
// and 2) may return unused_type if all elements have
// unused_type(s).
typedef typename
traits::build_fusion_vector<all_attributes>::type
type_;
// Finally, strip single element vectors into its
// naked form: vector1<T> --> T
typedef typename
traits::strip_single_element_vector<type_>::type
type;
};
// standard case. Attribute is a fusion tuple
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute, typename Pred1, typename Pred2>
bool generate_impl(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute& attr_, Pred1, Pred2) const
{
typedef detail::fail_function<
OutputIterator, Context, Delimiter> fail_function;
typedef traits::attribute_not_unused<Context> predicate;
// wrap the attribute in a tuple if it is not a tuple or if the
// attribute of this sequence is a single element tuple
typedef typename attribute<Context>::type_ attr_type_;
typename traits::wrap_if_not_tuple<Attribute
, typename mpl::and_<
traits::one_element_sequence<attr_type_>
, mpl::not_<traits::one_element_sequence<Attribute> >
>::type
>::type attr(attr_);
// return false if *any* of the generators fail
bool r = spirit::any_if(elements, attr
, fail_function(sink, ctx, d), predicate());
typedef typename traits::attribute_size<Attribute>::type size_type;
// fail generating if sequences have not the same (logical) length
return !r && (!Strict::value ||
// This ignores container element count (which is not good),
// but allows valid attributes to succeed. This will lead to
// false positives (failing generators, even if they shouldn't)
// if the embedded component is restricting the number of
// container elements it consumes (i.e. repeat). This solution
// is not optimal but much better than letting _all_ repetitive
// components fail.
Pred1::value ||
size_type(traits::sequence_size<attr_type_>::value) == traits::size(attr_));
}
// Special case when Attribute is an stl container and the sequence's
// attribute is not a one element sequence
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate_impl(OutputIterator& sink, Context& ctx
, Delimiter const& d, Attribute const& attr_
, mpl::true_, mpl::false_) const
{
// return false if *any* of the generators fail
typedef detail::fail_function<
OutputIterator, Context, Delimiter> fail_function;
typedef typename traits::container_iterator<
typename add_const<Attribute>::type
>::type iterator_type;
typedef
typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
fail_function, Attribute, indirect_iterator_type, mpl::true_>
pass_container;
iterator_type begin = traits::begin(attr_);
iterator_type end = traits::end(attr_);
pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(begin), indirect_iterator_type(end));
bool r = fusion::any(elements, pass);
// fail generating if sequences have not the same (logical) length
return !r && (!Strict::value || begin == end);
}
// main generate function. Dispatches to generate_impl depending
// on the Attribute type.
template <
typename OutputIterator, typename Context, typename Delimiter
, typename Attribute>
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
typedef typename traits::is_container<Attribute>::type
is_container;
typedef typename attribute<Context>::type_ attr_type_;
typedef typename traits::one_element_sequence<attr_type_>::type
is_one_element_sequence;
return generate_impl(sink, ctx, d, attr, is_container()
, is_one_element_sequence());
}
template <typename Context>
info what(Context& context) const
{
info result("sequence");
fusion::for_each(elements,
spirit::detail::what_function<Context>(result, context));
return result;
}
Elements elements;
};
template <typename Elements>
struct sequence
: base_sequence<Elements, mpl::false_, sequence<Elements> >
{
typedef base_sequence<Elements, mpl::false_, sequence> base_sequence_;
sequence(Elements const& subject)
: base_sequence_(subject) {}
};
template <typename Elements>
struct strict_sequence
: base_sequence<Elements, mpl::true_, strict_sequence<Elements> >
{
typedef base_sequence<Elements, mpl::true_, strict_sequence>
base_sequence_;
strict_sequence(Elements const& subject)
: base_sequence_(subject) {}
};
///////////////////////////////////////////////////////////////////////////
// Generator generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Elements, bool strict_mode = false>
struct make_sequence
: make_nary_composite<Elements, sequence>
{};
template <typename Elements>
struct make_sequence<Elements, true>
: make_nary_composite<Elements, strict_sequence>
{};
}
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::shift_left, Elements, Modifiers>
: detail::make_sequence<Elements, detail::get_stricttag<Modifiers>::value>
{};
///////////////////////////////////////////////////////////////////////////
// Helper template allowing to get the required container type for a rule
// attribute, which is part of a sequence.
template <typename Iterator>
struct make_sequence_iterator_range
{
typedef iterator_range<detail::indirect_iterator<Iterator> > type;
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Elements>
struct has_semantic_action<karma::sequence<Elements> >
: nary_has_semantic_action<Elements> {};
template <typename Elements>
struct has_semantic_action<karma::strict_sequence<Elements> >
: nary_has_semantic_action<Elements> {};
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::sequence<Elements>, Attribute, Context
, Iterator>
: mpl::true_ {};
template <typename Elements, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::strict_sequence<Elements>, Attribute
, Context, Iterator>
: mpl::true_ {};
}}}
#endif
@@ -0,0 +1,124 @@
// 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_PHOENIX_ATTRIBUTES_OCT_01_2009_1128AM)
#define BOOST_SPIRIT_KARMA_PHOENIX_ATTRIBUTES_OCT_01_2009_1128AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/version.hpp>
// we support Phoenix attributes only starting with V2.2
#if SPIRIT_VERSION >= 0x2020
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/utility/result_of.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// Provide customization points allowing the use of phoenix expressions as
// generator functions in the context of generators expecting a container
// attribute (Kleene, plus, list, repeat, etc.)
///////////////////////////////////////////////////////////////////////////
template <typename Eval>
struct is_container<phoenix::actor<Eval> const>
: is_container<typename boost::result_of<phoenix::actor<Eval>()>::type>
{};
template <typename Eval>
struct container_iterator<phoenix::actor<Eval> const>
{
typedef phoenix::actor<Eval> const& type;
};
template <typename Eval>
struct begin_container<phoenix::actor<Eval> const>
{
typedef phoenix::actor<Eval> const& type;
static type call(phoenix::actor<Eval> const& f)
{
return f;
}
};
template <typename Eval>
struct end_container<phoenix::actor<Eval> const>
{
typedef phoenix::actor<Eval> const& type;
static type call(phoenix::actor<Eval> const& f)
{
return f;
}
};
template <typename Eval>
struct deref_iterator<phoenix::actor<Eval> const>
{
typedef typename boost::result_of<phoenix::actor<Eval>()>::type type;
static type call(phoenix::actor<Eval> const& f)
{
return f();
}
};
template <typename Eval>
struct next_iterator<phoenix::actor<Eval> const>
{
typedef phoenix::actor<Eval> const& type;
static type call(phoenix::actor<Eval> const& f)
{
return f;
}
};
template <typename Eval>
struct compare_iterators<phoenix::actor<Eval> const>
{
static bool
call(phoenix::actor<Eval> const&, phoenix::actor<Eval> const&)
{
return false;
}
};
template <typename Eval>
struct container_value<phoenix::actor<Eval> >
{
typedef phoenix::actor<Eval> const& type;
};
template <typename Eval>
struct make_indirect_iterator<phoenix::actor<Eval> const>
{
typedef phoenix::actor<Eval> const& type;
};
///////////////////////////////////////////////////////////////////////////
// Handle Phoenix actors as attributes, just invoke the function object
// and deal with the result as the attribute.
///////////////////////////////////////////////////////////////////////////
template <typename Eval, typename Exposed>
struct extract_from_attribute<phoenix::actor<Eval>, Exposed>
{
typedef typename boost::result_of<phoenix::actor<Eval>()>::type type;
template <typename Context>
static type call(phoenix::actor<Eval> const& f, Context& context)
{
return f(unused, context);
}
};
}}}
#endif
#endif
@@ -0,0 +1,91 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_REFERENCE_APR_17_2009_1057PM)
#define BOOST_SPIRIT_KARMA_REFERENCE_APR_17_2009_1057PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/ref.hpp>
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// reference is a generator that references another generator (its Subject)
///////////////////////////////////////////////////////////////////////////
template <typename Subject>
struct reference : generator<reference<Subject> >
{
typedef mpl::int_<generator_properties::all_properties> properties;
typedef Subject subject_type;
reference(Subject& subject)
: ref(subject) {}
template <typename Context, typename Unused>
struct attribute : Subject::template attribute<Context, Unused> {};
// Default overload, used whenever the attribute is not unused and not
// used from an aliased rule.
template <typename OutputIterator, typename Context
, typename Delimiter, typename Attribute>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& delim, Attribute const& attr) const
{
return ref.get().generate(sink, context, delim, attr);
}
// This overload gets called from an aliased rule only, we take the
// attribute from the context provided from the wrapper rule.
template <typename OutputIterator, typename Context
, typename Delimiter>
bool generate(OutputIterator& sink, Context& context
, Delimiter const& delim, unused_type) const
{
return ref.get().generate(sink, context, delim, context.attributes);
}
// This overload is used whenever no attribute is given and it is used
// not from an aliased rule.
template <typename OutputIterator, typename Delimiter>
bool generate(OutputIterator& sink, unused_type
, Delimiter const& delim, unused_type) const
{
return ref.get().generate(sink, unused, delim, unused);
}
template <typename Context>
info what(Context& context) const
{
// the reference is transparent (does not add any info)
return ref.get().what(context);
}
boost::reference_wrapper<Subject> ref;
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Attribute, typename Context
, typename Iterator>
struct handles_container<karma::reference<Subject>, Attribute
, Context, Iterator>
: handles_container<typename remove_const<Subject>::type, Attribute
, Context, Iterator>
{};
}}}
#endif
@@ -0,0 +1,16 @@
// 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_STREAM_MAY_01_2007_1254AM)
#define BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_1254AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
#include <boost/spirit/home/karma/stream/stream.hpp>
#endif
@@ -0,0 +1,207 @@
// 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_FORMAT_MANIP_MAY_03_2007_1424PM)
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <iterator>
#include <string>
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
#include <boost/mpl/bool.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr
, typename CopyExpr = mpl::false_, typename CopyAttr = mpl::false_
, typename Delimiter = unused_type, typename Attribute = unused_type>
struct format_manip
{
// This assertion makes sure we don't hit the only code path which is
// not implemented (because it isn't needed), where both, the
// expression and the attribute need to be held as a copy.
BOOST_SPIRIT_ASSERT_MSG(!CopyExpr::value || !CopyAttr::value
, error_invalid_should_not_happen, ());
format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
: expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
format_manip(Expr const& xpr, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
: expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
Expr const& expr;
Delimiter const& delim;
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute const& attr;
private:
// silence MSVC warning C4512: assignment operator could not be generated
format_manip& operator= (format_manip const&);
};
template <typename Expr, typename Delimiter, typename Attribute>
struct format_manip<Expr, mpl::false_, mpl::true_, Delimiter, Attribute>
{
format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
: expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
format_manip(Expr const& xpr, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
: expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
Expr const& expr;
Delimiter const& delim;
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute attr;
private:
// silence MSVC warning C4512: assignment operator could not be generated
format_manip& operator= (format_manip const&);
};
template <typename Expr, typename Delimiter, typename Attribute>
struct format_manip<Expr, mpl::true_, mpl::false_, Delimiter, Attribute>
{
format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
: expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
format_manip(Expr const& xpr, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
: expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
Expr expr;
Delimiter const& delim;
BOOST_SCOPED_ENUM(delimit_flag) const pre;
Attribute const& attr;
private:
// silence MSVC warning C4512: assignment operator could not be generated
format_manip& operator= (format_manip const&);
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable = void>
struct format
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_format_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr>
struct format<Expr
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
typedef format_manip<Expr> type;
static type call(Expr const& expr)
{
return type(expr, unused, unused);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Delimiter, typename Enable = void>
struct format_delimited
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_format_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr, typename Delimiter>
struct format_delimited<Expr, Delimiter
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
typedef format_manip<Expr, mpl::false_, mpl::false_, Delimiter> type;
static type call(
Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the delimiter is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
return type(expr, delimiter, pre_delimit, unused);
}
};
///////////////////////////////////////////////////////////////////////////
template<typename Char, typename Traits, typename Expr
, typename CopyExpr, typename CopyAttr>
inline std::basic_ostream<Char, Traits> &
operator<< (std::basic_ostream<Char, Traits> &os
, format_manip<Expr, CopyExpr, CopyAttr> const& fm)
{
karma::ostream_iterator<Char, Char, Traits> sink(os);
if (!karma::generate (sink, fm.expr))
{
os.setstate(std::ios_base::failbit);
}
return os;
}
///////////////////////////////////////////////////////////////////////////
template<typename Char, typename Traits, typename Expr
, typename CopyExpr, typename CopyAttr, typename Attribute>
inline std::basic_ostream<Char, Traits> &
operator<< (std::basic_ostream<Char, Traits> &os
, format_manip<Expr, CopyExpr, CopyAttr, unused_type, Attribute> const& fm)
{
karma::ostream_iterator<Char, Char, Traits> sink(os);
if (!karma::generate(sink, fm.expr, fm.attr))
{
os.setstate(std::ios_base::failbit);
}
return os;
}
template<typename Char, typename Traits, typename Expr
, typename CopyExpr, typename CopyAttr, typename Delimiter>
inline std::basic_ostream<Char, Traits> &
operator<< (std::basic_ostream<Char, Traits> &os
, format_manip<Expr, CopyExpr, CopyAttr, Delimiter> const& fm)
{
karma::ostream_iterator<Char, Char, Traits> sink(os);
if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre))
{
os.setstate(std::ios_base::failbit);
}
return os;
}
///////////////////////////////////////////////////////////////////////////
template<typename Char, typename Traits, typename Expr
, typename CopyExpr, typename CopyAttr, typename Delimiter
, typename Attribute>
inline std::basic_ostream<Char, Traits> &
operator<< (std::basic_ostream<Char, Traits> &os
, format_manip<Expr, CopyExpr, CopyAttr, Delimiter, Attribute> const& fm)
{
karma::ostream_iterator<Char, Char, Traits> sink(os);
if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre, fm.attr))
{
os.setstate(std::ios_base::failbit);
}
return os;
}
}}}}
#endif
@@ -0,0 +1,56 @@
// 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_FORMAT_MANIP_AUTO_DEC_02_2009_1246PM)
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_AUTO_DEC_02_2009_1246PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/stream/detail/format_manip.hpp>
#include <boost/spirit/home/karma/auto/create_generator.hpp>
#include <boost/utility/enable_if.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct format<Expr
, typename enable_if<traits::meta_create_exists<karma::domain, Expr> >::type>
{
typedef typename result_of::create_generator<Expr>::type expr_type;
typedef format_manip<
expr_type, mpl::true_, mpl::false_, unused_type, Expr
> type;
static type call(Expr const& expr)
{
return type(create_generator<Expr>(), unused, expr);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Delimiter>
struct format_delimited<Expr, Delimiter
, typename enable_if<traits::meta_create_exists<karma::domain, Expr> >::type>
{
typedef typename result_of::create_generator<Expr>::type expr_type;
typedef format_manip<
expr_type, mpl::true_, mpl::false_, Delimiter, Expr
> type;
static type call(Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
return type(create_generator<Expr>(), delimiter, pre_delimit, expr);
}
};
}}}}
#endif
@@ -0,0 +1,55 @@
// 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.boist.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_ITERATOR_SINK_MAY_27_2007_0133PM)
#define BOOST_SPIRIT_ITERATOR_SINK_MAY_27_2007_0133PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/iostreams/stream.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <
typename OutputIterator, typename Char, typename CharEncoding
, typename Tag
>
struct iterator_sink
{
typedef boost::iostreams::sink_tag category;
typedef Char char_type;
iterator_sink (OutputIterator& sink_)
: sink(sink_)
{}
// Write up to n characters from the buffer s to the output sequence,
// returning the number of characters written
std::streamsize write (Char const* s, std::streamsize n)
{
std::streamsize bytes_written = 0;
while (n--) {
if (!generate_to(sink, *s, CharEncoding(), Tag()))
break;
++s; ++bytes_written;
}
return bytes_written;
}
OutputIterator& sink;
private:
// silence MSVC warning C4512: assignment operator could not be generated
iterator_sink& operator= (iterator_sink const&);
};
}}}}
#endif
@@ -0,0 +1,117 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_01_2007_1211PM)
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_01_2007_1211PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/karma/stream/detail/format_manip.hpp>
#include <boost/spirit/home/support/unused.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
inline typename detail::format<Expr>::type
format(Expr const& expr)
{
return detail::format<Expr>::call(expr);
}
template <typename Expr, typename Attribute>
inline detail::format_manip<Expr, mpl::false_, mpl::false_, unused_type, Attribute>
format(
Expr const& expr
, Attribute const& attr)
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
return format_manip<Expr, mpl::false_, mpl::false_, unused_type, Attribute>(
expr, unused, attr);
}
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Delimiter>
inline typename detail::format_delimited<Expr, Delimiter>::type
format_delimited(
Expr const& expr
, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit =
delimit_flag::dont_predelimit)
{
return detail::format_delimited<Expr, Delimiter>::call(expr, d, pre_delimit);
}
template <typename Expr, typename Delimiter, typename Attribute>
inline detail::format_manip<Expr, mpl::false_, mpl::false_, Delimiter, Attribute>
format_delimited(
Expr const& xpr
, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, Attribute const& attr)
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
return format_manip<Expr, mpl::false_, mpl::false_, Delimiter, Attribute>(
xpr, d, pre_delimit, attr);
}
template <typename Expr, typename Delimiter, typename Attribute>
inline detail::format_manip<Expr, mpl::false_, mpl::false_, Delimiter, Attribute>
format_delimited(
Expr const& xpr
, Delimiter const& d
, Attribute const& attr)
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
return format_manip<Expr, mpl::false_, mpl::false_, Delimiter, Attribute>(
xpr, d, delimit_flag::dont_predelimit, attr);
}
///////////////////////////////////////////////////////////////////////////
template<typename Char, typename Traits, typename Derived>
inline std::basic_ostream<Char, Traits> &
operator<< (std::basic_ostream<Char, Traits> &os, generator<Derived> const& g)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Derived>::type
> properties;
typedef karma::ostream_iterator<Char, Char, Traits> outiter_type;
outiter_type target_sink(os);
karma::detail::output_iterator<outiter_type, properties> sink(target_sink);
if (!g.derived().generate(sink, unused, unused, unused))
{
os.setstate(std::ios_base::failbit);
}
return os;
}
}}}
#endif
@@ -0,0 +1,123 @@
// 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_PP_IS_ITERATING)
#if !defined(BOOST_SPIRIT_KARMA_FORMAT_MANIP_ATTR_APR_24_2009_0734AM)
#define BOOST_SPIRIT_KARMA_FORMAT_MANIP_ATTR_APR_24_2009_0734AM
#include <boost/spirit/home/karma/stream/format_manip.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/preprocessor/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#define BOOST_PP_FILENAME_1 \
<boost/spirit/home/karma/stream/format_manip_attr.hpp>
#define BOOST_PP_ITERATION_LIMITS (2, SPIRIT_ARGUMENTS_LIMIT)
#include BOOST_PP_ITERATE()
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Preprocessor vertical repetition code
//
///////////////////////////////////////////////////////////////////////////////
#else // defined(BOOST_PP_IS_ITERATING)
#define N BOOST_PP_ITERATION()
#define BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE(z, n, A) \
BOOST_PP_CAT(A, n) const&
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline detail::format_manip<Expr, mpl::false_, mpl::true_, unused_type
, fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> >
format(Expr const& xpr, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
return format_manip<Expr, mpl::false_, mpl::true_, unused_type, vector_type>(
xpr, unused, attr);
}
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline detail::format_manip<Expr, mpl::false_, mpl::true_, Delimiter
, fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> >
format_delimited(Expr const& xpr, Delimiter const& d
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
return format_manip<Expr, mpl::false_, mpl::true_, Delimiter, vector_type>(
xpr, d, pre_delimit, attr);
}
template <typename Expr, typename Delimiter
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline detail::format_manip<Expr, mpl::false_, mpl::true_, Delimiter
, fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> >
format_delimited(Expr const& xpr, Delimiter const& d
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
{
using karma::detail::format_manip;
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
return format_manip<Expr, mpl::false_, mpl::true_, Delimiter, vector_type>(
xpr, d, delimit_flag::dont_predelimit, attr);
}
}}}
#undef BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE
#undef N
#endif
@@ -0,0 +1,65 @@
// 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_OSTREAM_ITERATOR_MAY_26_2007_1016PM)
#define BOOST_SPIRIT_KARMA_OSTREAM_ITERATOR_MAY_26_2007_1016PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <iterator>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
///////////////////////////////////////////////////////////////////////////
// We need our own implementation of an ostream_iterator just to be able
// to access the wrapped ostream, which is necessary for the
// stream_generator, where we must generate the output using the original
// ostream to retain possibly registered facets.
///////////////////////////////////////////////////////////////////////////
template <
typename T, typename Elem = char
, typename Traits = std::char_traits<Elem> >
class ostream_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
typedef Elem char_type;
typedef Traits traits_type;
typedef std::basic_ostream<Elem, Traits> ostream_type;
typedef ostream_iterator<T, Elem, Traits> self_type;
ostream_iterator(ostream_type& os_, Elem const* delim_ = 0)
: os(&os_), delim(delim_) {}
self_type& operator= (T const& val)
{
*os << val;
if (0 != delim)
*os << delim;
return *this;
}
self_type& operator*() { return *this; }
self_type& operator++() { return *this; }
self_type operator++(int) { return *this; }
// expose underlying stream
ostream_type& get_ostream() { return *os; }
ostream_type const& get_ostream() const { return *os; }
// expose good bit of underlying stream object
bool good() const { return get_ostream().good(); }
protected:
ostream_type *os;
Elem const* delim;
};
}}}
#endif

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