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