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

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,250 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
#define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/directive/buffer.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/detail/hold_any.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/variant.hpp>
#include <boost/detail/workaround.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// execute a generator if the given Attribute type is compatible
///////////////////////////////////////////////////////////////////////////
// this gets instantiated if the Attribute type is _not_ compatible with
// the generator
template <typename Component, typename Attribute, typename Expected
, typename Enable = void>
struct alternative_generate
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const&, OutputIterator&, Context&, Delimiter const&
, Attribute const&, bool& failed)
{
failed = true;
return false;
}
};
template <typename Component>
struct alternative_generate<Component, unused_type, unused_type>
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink, Context& ctx
, Delimiter const& d, unused_type, bool&)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators succeed
return component.generate(sink, ctx, d, unused);
}
};
// this gets instantiated if there is no Attribute given for the
// alternative generator
template <typename Component, typename Expected>
struct alternative_generate<Component, unused_type, Expected>
: alternative_generate<Component, unused_type, unused_type> {};
// this gets instantiated if the generator does not expect to receive an
// Attribute (the generator is self contained).
template <typename Component, typename Attribute>
struct alternative_generate<Component, Attribute, unused_type>
: alternative_generate<Component, unused_type, unused_type> {};
// this gets instantiated if the Attribute type is compatible to the
// generator
template <typename Component, typename Attribute, typename Expected>
struct alternative_generate<Component, Attribute, Expected
, typename enable_if<
traits::compute_compatible_component<Expected, Attribute, karma::domain> >::type>
{
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
return call(component, sink, ctx, d, attr
, spirit::traits::not_is_variant<Attribute, karma::domain>());
}
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
return component.generate(sink, ctx, d, attr);
}
template <typename OutputIterator, typename Context, typename Delimiter>
static bool
call(Component const& component, OutputIterator& sink
, Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
typedef
traits::compute_compatible_component<Expected, Attribute, domain>
component_type;
// if we got passed an empty optional, just fail generation
if (!traits::has_optional_value(attr))
return false;
// make sure, the content of the passed variant matches our
// expectations
typename traits::optional_attribute<Attribute>::type attr_ =
traits::optional_value(attr);
if (!component_type::is_compatible(spirit::traits::which(attr_)))
return false;
// returns true if any of the generators succeed
typedef typename component_type::compatible_type compatible_type;
return component.generate(sink, ctx, d
, boost::get<compatible_type>(attr_));
}
};
///////////////////////////////////////////////////////////////////////////
// alternative_generate_function: a functor supplied to fusion::any which
// will be executed for every generator in a given alternative generator
// expression
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute, typename Strict>
struct alternative_generate_function
{
alternative_generate_function(OutputIterator& sink_, Context& ctx_
, Delimiter const& d, Attribute const& attr_)
: sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
template <typename Component>
bool operator()(Component const& component)
{
typedef
typename traits::attribute_of<Component, Context>::type
expected_type;
typedef
alternative_generate<Component, Attribute, expected_type>
generate;
// wrap the given output iterator avoid output as long as one
// component fails
detail::enable_buffering<OutputIterator> buffering(sink);
bool r = false;
bool failed = false; // will be ignored
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = generate::call(component, sink, ctx, delim, attr, failed);
}
if (r)
buffering.buffer_copy();
return r;
}
// avoid double buffering
template <typename Component>
bool operator()(buffer_directive<Component> const& component)
{
typedef typename
traits::attribute_of<Component, Context>::type
expected_type;
typedef alternative_generate<
buffer_directive<Component>, Attribute, expected_type>
generate;
bool failed = false; // will be ignored
return generate::call(component, sink, ctx, delim, attr, failed);
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
Attribute const& attr;
private:
// silence MSVC warning C4512: assignment operator could not be generated
alternative_generate_function& operator= (alternative_generate_function const&);
};
// specialization for strict alternatives
template <typename OutputIterator, typename Context, typename Delimiter,
typename Attribute>
struct alternative_generate_function<
OutputIterator, Context, Delimiter, Attribute, mpl::true_>
{
alternative_generate_function(OutputIterator& sink_, Context& ctx_
, Delimiter const& d, Attribute const& attr_)
: sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
template <typename Component>
bool operator()(Component const& component)
{
typedef
typename traits::attribute_of<Component, Context>::type
expected_type;
typedef
alternative_generate<Component, Attribute, expected_type>
generate;
if (failed)
return false; // give up when already failed
// wrap the given output iterator avoid output as long as one
// component fails
detail::enable_buffering<OutputIterator> buffering(sink);
bool r = false;
{
detail::disable_counting<OutputIterator> nocounting(sink);
r = generate::call(component, sink, ctx, delim, attr, failed);
}
if (r && !failed)
{
buffering.buffer_copy();
return true;
}
return false;
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
Attribute const& attr;
bool failed;
private:
// silence MSVC warning C4512: assignment operator could not be generated
alternative_generate_function& operator= (alternative_generate_function const&);
};
}}}}
#endif
@@ -0,0 +1,74 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_AS_STRING_DEC_18_0644PM)
#define BOOST_SPIRIT_KARMA_AS_STRING_DEC_18_0644PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// This file contains the attribute to string conversion utility. The
// utility provided also accept spirit's unused_type; all no-ops. Compiler
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Attribute>
inline typename spirit::result_of::attribute_as<T, Attribute>::type
as(Attribute const& attr)
{
return attribute_as<T, Attribute>::call(attr);
}
template <typename T>
inline unused_type as(unused_type)
{
return unused;
}
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Attribute>
inline bool valid_as(Attribute const& attr)
{
return attribute_as<T, Attribute>::is_valid(attr);
}
template <typename T>
inline bool valid_as(unused_type)
{
return true;
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
template <typename T, typename Attribute>
struct attribute_as
: traits::attribute_as<T, Attribute>
{};
template <typename T>
struct attribute_as<T, unused_type>
{
typedef unused_type type;
};
template <typename T>
struct attribute_as<T, unused_type const>
{
typedef unused_type type;
};
}}}
#endif
@@ -0,0 +1,108 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_DETAIL_ATTRIBUTES_APR_18_2010_0453PM)
#define SPIRIT_KARMA_DETAIL_ATTRIBUTES_APR_18_2010_0453PM
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/support/attributes.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma
{
template <typename Exposed, typename Transformed, typename Enable = void>
struct transform_attribute
{
typedef Transformed type;
static Transformed pre(Exposed& val)
{
return Transformed(traits::extract_from<Transformed>(val, unused));
}
// Karma only, no post() and no fail() required
};
template <typename Exposed, typename Transformed>
struct transform_attribute<boost::optional<Exposed> const, Transformed
, typename disable_if<is_same<boost::optional<Exposed>, Transformed> >::type>
{
typedef Transformed const& type;
static Transformed const& pre(boost::optional<Exposed> const& val)
{
return boost::get<Transformed>(val);
}
};
template <typename Attribute>
struct transform_attribute<Attribute const, Attribute>
{
typedef Attribute const& type;
static Attribute const& pre(Attribute const& val) { return val; }
// Karma only, no post() and no fail() required
};
// reference types need special handling
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed&, Transformed>
: transform_attribute<Exposed, Transformed>
{};
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed const&, Transformed>
: transform_attribute<Exposed const, Transformed>
{};
template <typename Attribute>
struct transform_attribute<Attribute const&, Attribute>
: transform_attribute<Attribute const, Attribute>
{};
// unused_type needs some special handling as well
template <>
struct transform_attribute<unused_type, unused_type>
{
typedef unused_type type;
static unused_type pre(unused_type) { return unused; }
};
template <>
struct transform_attribute<unused_type const, unused_type>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<unused_type, Attribute>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<unused_type const, Attribute>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<Attribute, unused_type>
: transform_attribute<unused_type, unused_type>
{};
template <typename Attribute>
struct transform_attribute<Attribute const, unused_type>
: transform_attribute<unused_type, unused_type>
{};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
template <typename Exposed, typename Transformed>
struct transform_attribute<Exposed, Transformed, karma::domain>
: karma::transform_attribute<Exposed, Transformed>
{};
}}}
#endif
@@ -0,0 +1,75 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DEFAULT_WIDTH_APR_07_2009_0912PM)
#define BOOST_SPIRIT_KARMA_DEFAULT_WIDTH_APR_07_2009_0912PM
#if defined(_MSC_VER)
#pragma once
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_FIELD_LENGTH specifies the default field length
// to be used for padding.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_FIELD_LENGTH)
#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 10
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH specifies the default maximal field
// length to be used for the maxwidth directive.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH)
#define BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH 10
#endif
///////////////////////////////////////////////////////////////////////////////
//
// The BOOST_KARMA_DEFAULT_COLUMNS specifies the default number of columns to
// be used with the columns directive.
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_KARMA_DEFAULT_COLUMNS)
#define BOOST_KARMA_DEFAULT_COLUMNS 5
#endif
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
struct default_width
{
operator int() const
{
return BOOST_KARMA_DEFAULT_FIELD_LENGTH;
}
};
///////////////////////////////////////////////////////////////////////////
struct default_max_width
{
operator int() const
{
return BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH;
}
};
///////////////////////////////////////////////////////////////////////////
struct default_columns
{
operator int() const
{
return BOOST_KARMA_DEFAULT_COLUMNS;
}
};
}}}}
#endif
@@ -0,0 +1,30 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DETAIL_ENABLE_LIT_JAN_06_2011_1009PM)
#define BOOST_SPIRIT_KARMA_DETAIL_ENABLE_LIT_JAN_06_2011_1009PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/domain.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit
{
// enables lazy lit(...) for karma
template <>
struct use_lazy_terminal<karma::domain, tag::lit, 1>
: mpl::true_ {};
}}
#endif
@@ -0,0 +1,274 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM)
#define BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/ref.hpp>
#include <boost/optional.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// This file contains attribute extraction utilities. The utilities
// provided also accept spirit's unused_type; all no-ops. Compiler
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
// extract first and second element of a fusion sequence
template <typename T>
struct add_const_ref
: add_reference<typename add_const<T>::type>
{};
template <typename T, int N>
struct value_at_c
: add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
{};
}
// This is the default case: the plain attribute values
template <typename Attribute, typename Exposed, typename Enable/*= void*/>
struct extract_from_attribute
{
typedef typename traits::one_element_sequence<Attribute>::type
is_one_element_sequence;
typedef typename mpl::eval_if<
is_one_element_sequence
, detail::value_at_c<Attribute, 0>
, mpl::identity<Attribute const&>
>::type type;
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_)
{
return attr;
}
// This handles the case where the attribute is a single element fusion
// sequence. We silently extract the only element and treat it as the
// attribute to generate output from.
template <typename Context>
static type call(Attribute const& attr, Context& ctx, mpl::true_)
{
return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
}
template <typename Context>
static type call(Attribute const& attr, Context& ctx)
{
return call(attr, ctx, is_one_element_sequence());
}
};
// This handles optional attributes.
template <typename Attribute, typename Exposed>
struct extract_from_attribute<boost::optional<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(boost::optional<Attribute> const& attr, Context& ctx)
{
return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
}
};
template <typename Attribute, typename Exposed>
struct extract_from_attribute<boost::optional<Attribute const>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(boost::optional<Attribute const> const& attr, Context& ctx)
{
return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
}
};
// This handles attributes wrapped inside a boost::ref().
template <typename Attribute, typename Exposed>
struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
{
typedef Attribute const& type;
template <typename Context>
static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
{
return extract_from<Exposed>(attr.get(), ctx);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Attribute, typename Exposed, typename Enable>
struct extract_from_container
{
typedef typename traits::container_value<Attribute const>::type
value_type;
typedef typename is_convertible<value_type, Exposed>::type
is_convertible_to_value_type;
typedef typename mpl::if_<
mpl::or_<
is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
, Exposed const&, Exposed
>::type type;
// handle case where container value type is convertible to result type
// we simply return the front element of the container
template <typename Context, typename Pred>
static type call(Attribute const& attr, Context&, mpl::true_, Pred)
{
// return first element from container
typedef typename traits::container_iterator<Attribute const>::type
iterator_type;
iterator_type it = traits::begin(attr);
type result = *it;
++it;
return result;
}
// handle strings
template <typename Iterator>
static void append_to_string(Exposed& result, Iterator begin, Iterator end)
{
for (Iterator i = begin; i != end; ++i)
push_back(result, *i);
}
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_, mpl::true_)
{
typedef typename char_type_of<Attribute>::type char_type;
Exposed result;
append_to_string(result, traits::get_begin<char_type>(attr)
, traits::get_end<char_type>(attr));
return result;
}
// everything else gets just passed through
template <typename Context>
static type call(Attribute const& attr, Context&, mpl::false_, mpl::false_)
{
return type(attr);
}
template <typename Context>
static type call(Attribute const& attr, Context& ctx)
{
typedef typename mpl::and_<
traits::is_string<Exposed>, traits::is_string<Attribute>
>::type handle_strings;
// return first element from container
return call(attr, ctx, is_convertible_to_value_type()
, handle_strings());
}
};
template <typename Attribute>
struct extract_from_container<Attribute, Attribute>
{
typedef Attribute const& type;
template <typename Context>
static type call(Attribute const& attr, Context&)
{
return attr;
}
};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
// overload for non-container attributes
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx, mpl::false_)
{
return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
}
// overload for containers (but not for variants or optionals
// holding containers)
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx, mpl::true_)
{
return extract_from_container<Attribute, Exposed>::call(attr, ctx);
}
}
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
extract_from(Attribute const& attr, Context& ctx
#if (defined(__GNUC__) && (__GNUC__ < 4)) || \
(defined(__APPLE__) && defined(__INTEL_COMPILER))
, typename enable_if<traits::not_is_unused<Attribute> >::type*
#endif
)
{
typedef typename mpl::and_<
traits::is_container<Attribute>
, traits::not_is_variant<Attribute>
, traits::not_is_optional<Attribute>
>::type is_not_wrapped_container;
return detail::extract_from<Exposed>(attr, ctx
, is_not_wrapped_container());
}
template <typename Exposed, typename Context>
inline unused_type extract_from(unused_type, Context&)
{
return unused;
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
template <typename Exposed, typename Attribute>
struct extract_from
: mpl::if_<
mpl::and_<
traits::is_container<Attribute>
, traits::not_is_variant<Attribute>
, traits::not_is_optional<Attribute> >
, traits::extract_from_container<Attribute, Exposed>
, traits::extract_from_attribute<Attribute, Exposed> >::type
{};
template <typename Exposed>
struct extract_from<Exposed, unused_type>
{
typedef unused_type type;
};
template <typename Exposed>
struct extract_from<Exposed, unused_type const>
{
typedef unused_type type;
};
}}}
#endif
@@ -0,0 +1,60 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0249PM)
#define SPIRIT_KARMA_SEQUENCE_FEB_28_2007_0249PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/config.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename OutputIterator, typename Context, typename Delimiter>
struct fail_function
{
typedef Context context_type;
fail_function(OutputIterator& sink_, Context& context_
, Delimiter const& delim_)
: sink(sink_), ctx(context_), delim(delim_)
{}
template <typename Component, typename Attribute>
bool operator()(Component const& component, Attribute const& attr) const
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators fail
return !component.generate(sink, ctx, delim, attr);
}
template <typename Component>
bool operator()(Component const& component) const
{
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
#endif
// return true if any of the generators fail
return !component.generate(sink, ctx, delim, unused);
}
OutputIterator& sink;
Context& ctx;
Delimiter const& delim;
private:
// silence MSVC warning C4512: assignment operator could not be generated
fail_function& operator= (fail_function const&);
};
}}}}
#endif
@@ -0,0 +1,131 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DETAIL_GENERATE_FEB_20_2007_0959AM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_FEB_20_2007_0959AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/meta_compiler.hpp>
#include <boost/spirit/home/karma/delimit_out.hpp>
#include <boost/spirit/home/karma/delimit_flag.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable = void>
struct generate_impl
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr>
struct generate_impl<Expr
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
template <typename OutputIterator>
static bool call(
OutputIterator& target_sink
, Expr const& expr)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
// wrap user supplied iterator into our own output iterator
output_iterator<OutputIterator
, mpl::int_<properties::value> > sink(target_sink);
return compile<karma::domain>(expr).
generate(sink, unused, unused, unused);
}
template <typename OutputIterator, typename Properties>
static bool call(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr)
{
return compile<karma::domain>(expr).
generate(sink, unused, unused, unused);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr, typename Enable = void>
struct generate_delimited_impl
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (Expr) is not a valid spirit karma expression.
// Did you intend to use the auto_ facilities while forgetting to
// #include <boost/spirit/include/karma_auto.hpp>?
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
};
template <typename Expr>
struct generate_delimited_impl<Expr
, typename enable_if<traits::matches<karma::domain, Expr> >::type>
{
template <typename OutputIterator, typename Delimiter>
static bool call(
OutputIterator& target_sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
typedef traits::properties_of<
typename result_of::compile<karma::domain, Expr>::type
> properties;
typedef traits::properties_of<
typename result_of::compile<karma::domain, Delimiter>::type
> delimiter_properties;
// wrap user supplied iterator into our own output iterator
detail::output_iterator<OutputIterator
, mpl::int_<properties::value | delimiter_properties::value>
> sink(target_sink);
return call(sink, expr, delimiter, pre_delimit);
}
template <typename OutputIterator, typename Properties
, typename Delimiter>
static bool call(
detail::output_iterator<OutputIterator, Properties>& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the delimiter is not a valid spirit karma expression.
BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
typename result_of::compile<karma::domain, Delimiter>::type const
delimiter_ = compile<karma::domain>(delimiter);
if (pre_delimit == delimit_flag::predelimit &&
!karma::delimit_out(sink, delimiter_))
{
return false;
}
return compile<karma::domain>(expr).
generate(sink, unused, delimiter_, unused);
}
};
}}}}
#endif
@@ -0,0 +1,63 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DETAIL_GENERATE_AUTO_DEC_01_2009_0743PM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_AUTO_DEC_01_2009_0743PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/generate.hpp>
#include <boost/spirit/home/karma/auto/create_generator.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/and.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct generate_impl<Expr
, typename enable_if<
mpl::and_<
traits::meta_create_exists<karma::domain, Expr>
, mpl::not_<traits::matches<karma::domain, Expr> > >
>::type>
{
template <typename OutputIterator>
static bool call(
OutputIterator& sink
, Expr const& expr)
{
return karma::generate(sink, create_generator<Expr>(), expr);
}
};
///////////////////////////////////////////////////////////////////////////
template <typename Expr>
struct generate_delimited_impl<Expr
, typename enable_if<
mpl::and_<
traits::meta_create_exists<karma::domain, Expr>
, mpl::not_<traits::matches<karma::domain, Expr> > >
>::type>
{
template <typename OutputIterator, typename Delimiter>
static bool call(
OutputIterator& sink
, Expr const& expr
, Delimiter const& delimiter
, BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
{
return karma::generate_delimited(
sink, create_generator<Expr>(), delimiter, pre_delimit, expr);
}
};
}}}}
#endif
@@ -0,0 +1,67 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_DETAIL_GENERATE_TO_FEB_20_2007_0417PM)
#define BOOST_SPIRIT_KARMA_DETAIL_GENERATE_TO_FEB_20_2007_0417PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/output_iterator.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// These utility functions insert the given parameter into the supplied
// output iterator.
// If the attribute is spirit's unused_type, this is a no_op.
///////////////////////////////////////////////////////////////////////////
template <
typename OutputIterator, typename Attribute, typename CharEncoding
, typename Tag>
inline bool
generate_to(OutputIterator& sink, Attribute const& p, CharEncoding, Tag)
{
*sink = spirit::char_class::convert<CharEncoding>::to(Tag(), p);
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename Attribute>
inline bool
generate_to(OutputIterator& sink, Attribute const& p, unused_type, unused_type)
{
*sink = p;
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename CharEncoding, typename Tag>
inline bool generate_to(OutputIterator&, unused_type, CharEncoding, Tag)
{
return true;
}
template <typename OutputIterator, typename Attribute>
inline bool
generate_to(OutputIterator& sink, Attribute const& p)
{
*sink = p;
++sink;
return detail::sink_is_good(sink);
}
template <typename OutputIterator>
inline bool generate_to(OutputIterator&, unused_type)
{
return true;
}
}}}} // namespace boost::spirit::karma::detail
#endif // KARMA_CORE_DETAIL_INSERT_TO_HPP
@@ -0,0 +1,29 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_GET_CASETAG_JANUARY_19_2009_1107AM)
#define BOOST_SPIRIT_KARMA_GET_CASETAG_JANUARY_19_2009_1107AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/identity.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Modifiers, bool case_modifier = false>
struct get_casetag : mpl::identity<unused_type> {};
template <typename Modifiers>
struct get_casetag<Modifiers, true>
: mpl::if_<has_modifier<Modifiers, tag::char_code_base<tag::lower> >
, tag::lower, tag::upper> {};
}}}}
#endif
@@ -0,0 +1,33 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM)
#define BOOST_SPIRIT_KARMA_GET_STRICTTAG_APR_22_2010_1007AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/or.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
// the default mode for Karma is 'relaxed'
template <
typename Modifiers
, typename StrictModifier = typename mpl::or_<
has_modifier<Modifiers, tag::strict>
, has_modifier<Modifiers, tag::relaxed> >::type>
struct get_stricttag : mpl::false_ {};
// strict mode is enforced only when tag::strict is on the modifiers list
template <typename Modifiers>
struct get_stricttag<Modifiers, mpl::true_>
: has_modifier<Modifiers, tag::strict> {};
}}}}
#endif
@@ -0,0 +1,98 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(SPIRIT_KARMA_INDIRECT_ITERATOR_JAN_19_2011_0814PM)
#define SPIRIT_KARMA_INDIRECT_ITERATOR_JAN_19_2011_0814PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/iterator/iterator_facade.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////
// This is a wrapper for any iterator allowing to pass a reference of it
// to the components of the sequence
template <typename Iterator>
class indirect_iterator
: public boost::iterator_facade<
indirect_iterator<Iterator>
, typename boost::detail::iterator_traits<Iterator>::value_type
, boost::forward_traversal_tag
, typename boost::detail::iterator_traits<Iterator>::reference>
{
typedef typename boost::detail::iterator_traits<Iterator>::value_type
base_value_type;
typedef typename boost::detail::iterator_traits<Iterator>::reference
base_reference_type;
typedef boost::iterator_facade<
indirect_iterator<Iterator>, base_value_type
, boost::forward_traversal_tag, base_reference_type
> base_type;
public:
indirect_iterator(Iterator& iter)
: iter_(&iter)
{}
indirect_iterator(indirect_iterator const& iter)
: iter_(iter.iter_)
{}
private:
friend class boost::iterator_core_access;
void increment()
{
++*iter_;
}
bool equal(indirect_iterator const& other) const
{
return *iter_ == *other.iter_;
}
base_reference_type dereference() const
{
return **iter_;
}
private:
Iterator* iter_;
};
}}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
template <typename Iterator>
struct make_indirect_iterator
{
typedef karma::detail::indirect_iterator<Iterator> type;
};
template <typename Iterator>
struct make_indirect_iterator<karma::detail::indirect_iterator<Iterator> >
{
typedef karma::detail::indirect_iterator<Iterator> type;
};
template <>
struct make_indirect_iterator<unused_type const*>
{
typedef unused_type const* type;
};
template <typename Iterator>
struct make_indirect_iterator<Iterator const&>
: make_indirect_iterator<Iterator const>
{};
}}}
#endif
@@ -0,0 +1,644 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM)
#define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <iterator>
#include <vector>
#include <algorithm>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/mpl/if.hpp>
#include <boost/spirit/home/karma/generator.hpp>
#include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
#include <boost/spirit/home/support/unused.hpp>
#if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
#include <boost/spirit/home/support/char_encoding/unicode.hpp>
#endif
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// This class is used to keep track of the current position in the output.
///////////////////////////////////////////////////////////////////////////
class position_sink
{
public:
position_sink() : count(0), line(1), column(1) {}
void tidy() { count = 0; line = 1; column = 1; }
template <typename T>
void output(T const& value)
{
++count;
if (value == '\n') {
++line;
column = 1;
}
else {
++column;
}
}
std::size_t get_count() const { return count; }
std::size_t get_line() const { return line; }
std::size_t get_column() const { return column; }
private:
std::size_t count;
std::size_t line;
std::size_t column;
};
///////////////////////////////////////////////////////////////////////////
struct position_policy
{
position_policy() {}
position_policy(position_policy const& rhs)
: track_position_data(rhs.track_position_data) {}
template <typename T>
void output(T const& value)
{
// track position in the output
track_position_data.output(value);
}
// return the current count in the output
std::size_t get_out_count() const
{
return track_position_data.get_count();
}
// return the current line in the output
std::size_t get_line() const
{
return track_position_data.get_line();
}
// return the current column in the output
std::size_t get_column() const
{
return track_position_data.get_column();
}
private:
position_sink track_position_data; // for position tracking
};
struct no_position_policy
{
no_position_policy() {}
no_position_policy(no_position_policy const&) {}
template <typename T>
void output(T const& /*value*/) {}
};
///////////////////////////////////////////////////////////////////////////
// This class is used to count the number of characters streamed into the
// output.
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
class counting_sink : boost::noncopyable
{
public:
counting_sink(OutputIterator& sink_, std::size_t count_ = 0
, bool enabled = true)
: count(count_), initial_count(count), prev_count(0), sink(sink_)
{
prev_count = sink.chain_counting(enabled ? this : NULL);
}
~counting_sink()
{
if (prev_count) // propagate count
prev_count->update_count(count-initial_count);
sink.chain_counting(prev_count);
}
void output()
{
++count;
}
std::size_t get_count() const { return count; }
// propagate count from embedded counters
void update_count(std::size_t c)
{
count += c;
}
private:
std::size_t count;
std::size_t initial_count;
counting_sink* prev_count; // previous counter in chain
OutputIterator& sink;
};
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct counting_policy
{
public:
counting_policy() : count(NULL) {}
counting_policy(counting_policy const& rhs) : count(rhs.count) {}
// functions related to counting
counting_sink<OutputIterator>* chain_counting(
counting_sink<OutputIterator>* count_data)
{
counting_sink<OutputIterator>* prev_count = count;
count = count_data;
return prev_count;
}
template <typename T>
void output(T const&)
{
// count characters, if appropriate
if (NULL != count)
count->output();
}
private:
counting_sink<OutputIterator>* count; // for counting
};
struct no_counting_policy
{
no_counting_policy() {}
no_counting_policy(no_counting_policy const&) {}
template <typename T>
void output(T const& /*value*/) {}
};
///////////////////////////////////////////////////////////////////////////
// The following classes are used to intercept the output into a buffer
// allowing to do things like alignment, character escaping etc.
///////////////////////////////////////////////////////////////////////////
class buffer_sink : boost::noncopyable
{
// wchar_t is only 16-bits on Windows. If BOOST_SPIRIT_UNICODE is
// defined, the character type is 32-bits wide so we need to make
// sure the buffer is at least that wide.
#if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
typedef spirit::char_encoding::unicode::char_type buffer_char_type;
#else
typedef wchar_t buffer_char_type;
#endif
public:
buffer_sink()
: width(0) {}
~buffer_sink()
{
tidy();
}
void enable(std::size_t width_)
{
tidy(); // release existing buffer
width = (width_ == std::size_t(-1)) ? 0 : width_;
buffer.reserve(width);
}
void tidy()
{
buffer.clear();
width = 0;
}
template <typename T>
void output(T const& value)
{
BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(buffer_char_type));
buffer.push_back(value);
}
template <typename OutputIterator_>
bool copy(OutputIterator_& sink, std::size_t maxwidth) const
{
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable: 4267)
#endif
typename std::basic_string<buffer_char_type>::const_iterator end =
buffer.begin() + (std::min)(buffer.size(), maxwidth);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
std::copy(buffer.begin(), end, sink);
return true;
}
template <typename RestIterator>
bool copy_rest(RestIterator& sink, std::size_t start_at) const
{
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable: 4267)
#endif
typename std::basic_string<buffer_char_type>::const_iterator begin =
buffer.begin() + (std::min)(buffer.size(), start_at);
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
std::copy(begin, buffer.end(), sink);
return true;
}
std::size_t buffer_size() const
{
return buffer.size();
}
private:
std::size_t width;
std::basic_string<buffer_char_type> buffer;
};
///////////////////////////////////////////////////////////////////////////
struct buffering_policy
{
public:
buffering_policy() : buffer(NULL) {}
buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
// functions related to buffering
buffer_sink* chain_buffering(buffer_sink* buffer_data)
{
buffer_sink* prev_buffer = buffer;
buffer = buffer_data;
return prev_buffer;
}
template <typename T>
bool output(T const& value)
{
// buffer characters, if appropriate
if (NULL != buffer) {
buffer->output(value);
return false;
}
return true;
}
bool has_buffer() const { return NULL != buffer; }
private:
buffer_sink* buffer;
};
struct no_buffering_policy
{
no_buffering_policy() {}
no_buffering_policy(no_counting_policy const&) {}
template <typename T>
bool output(T const& /*value*/)
{
return true;
}
bool has_buffer() const { return false; }
};
///////////////////////////////////////////////////////////////////////////
// forward declaration only
template <typename OutputIterator>
struct enable_buffering;
template <typename OutputIterator, typename Properties
, typename Derived = unused_type>
class output_iterator;
///////////////////////////////////////////////////////////////////////////
template <typename Buffering, typename Counting, typename Tracking>
struct output_iterator_base : Buffering, Counting, Tracking
{
typedef Buffering buffering_policy;
typedef Counting counting_policy;
typedef Tracking tracking_policy;
output_iterator_base() {}
output_iterator_base(output_iterator_base const& rhs)
: buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
{}
template <typename T>
bool output(T const& value)
{
this->counting_policy::output(value);
this->tracking_policy::output(value);
return this->buffering_policy::output(value);
}
};
template <typename Buffering, typename Counting, typename Tracking>
struct disabling_output_iterator : Buffering, Counting, Tracking
{
typedef Buffering buffering_policy;
typedef Counting counting_policy;
typedef Tracking tracking_policy;
disabling_output_iterator() : do_output(true) {}
disabling_output_iterator(disabling_output_iterator const& rhs)
: buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
, do_output(rhs.do_output)
{}
template <typename T>
bool output(T const& value)
{
if (!do_output)
return false;
this->counting_policy::output(value);
this->tracking_policy::output(value);
return this->buffering_policy::output(value);
}
bool do_output;
};
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Derived>
struct make_output_iterator
{
// get the most derived type of this class
typedef typename mpl::if_<
traits::not_is_unused<Derived>, Derived
, output_iterator<OutputIterator, Properties, Derived>
>::type most_derived_type;
enum { properties = Properties::value };
typedef typename mpl::if_c<
(properties & generator_properties::tracking) ? true : false
, position_policy, no_position_policy
>::type tracking_type;
typedef typename mpl::if_c<
(properties & generator_properties::buffering) ? true : false
, buffering_policy, no_buffering_policy
>::type buffering_type;
typedef typename mpl::if_c<
(properties & generator_properties::counting) ? true : false
, counting_policy<most_derived_type>, no_counting_policy
>::type counting_type;
typedef typename mpl::if_c<
(properties & generator_properties::disabling) ? true : false
, disabling_output_iterator<buffering_type, counting_type, tracking_type>
, output_iterator_base<buffering_type, counting_type, tracking_type>
>::type type;
};
///////////////////////////////////////////////////////////////////////////
// Karma uses an output iterator wrapper for all output operations. This
// is necessary to avoid the dreaded 'scanner business' problem, i.e. the
// dependency of rules and grammars on the used output iterator.
//
// By default the user supplied output iterator is wrapped inside an
// instance of this internal output_iterator class.
//
// This output_iterator class normally just forwards to the embedded user
// supplied iterator. But it is possible to enable additional functionality
// on demand, such as counting, buffering, and position tracking.
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Properties, typename Derived>
class output_iterator
: public make_output_iterator<OutputIterator, Properties, Derived>::type
{
private:
// base iterator type
typedef typename make_output_iterator<
OutputIterator, Properties, Derived>::type base_iterator;
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
explicit output_iterator(OutputIterator& sink_)
: sink(&sink_)
{}
output_iterator(output_iterator const& rhs)
: base_iterator(rhs), sink(rhs.sink)
{}
output_iterator& operator*() { return *this; }
output_iterator& operator++()
{
if (!this->base_iterator::has_buffer())
++(*sink); // increment only if not buffering
return *this;
}
output_iterator operator++(int)
{
if (!this->base_iterator::has_buffer()) {
output_iterator t(*this);
++(*sink);
return t;
}
return *this;
}
#if defined(BOOST_MSVC)
// 'argument' : conversion from '...' to '...', possible loss of data
#pragma warning (push)
#pragma warning (disable: 4244)
#endif
template <typename T>
void operator=(T const& value)
{
if (this->base_iterator::output(value))
*(*sink) = value;
}
#if defined(BOOST_MSVC)
#pragma warning (pop)
#endif
// plain output iterators are considered to be good all the time
bool good() const { return true; }
// allow to access underlying output iterator
OutputIterator& base() { return *sink; }
protected:
// this is the wrapped user supplied output iterator
OutputIterator* sink;
};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Elem, typename Traits, typename Properties>
class output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
: public output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
, output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties> >
{
private:
typedef output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
, output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
> base_type;
typedef karma::ostream_iterator<T, Elem, Traits> base_iterator_type;
typedef std::basic_ostream<Elem, Traits> ostream_type;
public:
output_iterator(base_iterator_type& sink)
: base_type(sink) {}
ostream_type& get_ostream() { return (*this->sink).get_ostream(); }
ostream_type const& get_ostream() const { return (*this->sink).get_ostream(); }
// expose good bit of underlying stream object
bool good() const { return (*this->sink).get_ostream().good(); }
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe enabling of character counting in the
// output iterator
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct enable_counting
{
enable_counting(OutputIterator& sink_, std::size_t count = 0)
: count_data(sink_, count) {}
// get number of characters counted since last enable
std::size_t count() const
{
return count_data.get_count();
}
private:
counting_sink<OutputIterator> count_data; // for counting
};
template <typename OutputIterator>
struct disable_counting
{
disable_counting(OutputIterator& sink_)
: count_data(sink_, 0, false) {}
private:
counting_sink<OutputIterator> count_data;
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe enabling of character buffering in the
// output iterator
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct enable_buffering
{
enable_buffering(OutputIterator& sink_
, std::size_t width = std::size_t(-1))
: sink(sink_), prev_buffer(NULL), enabled(false)
{
buffer_data.enable(width);
prev_buffer = sink.chain_buffering(&buffer_data);
enabled = true;
}
~enable_buffering()
{
disable();
}
// reset buffer chain to initial state
void disable()
{
if (enabled) {
BOOST_VERIFY(&buffer_data == sink.chain_buffering(prev_buffer));
enabled = false;
}
}
// copy to the underlying sink whatever is in the local buffer
bool buffer_copy(std::size_t maxwidth = std::size_t(-1)
, bool disable_ = true)
{
if (disable_)
disable();
return buffer_data.copy(sink, maxwidth) && sink.good();
}
// return number of characters stored in the buffer
std::size_t buffer_size() const
{
return buffer_data.buffer_size();
}
// copy to the remaining characters to the specified sink
template <typename RestIterator>
bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0) const
{
return buffer_data.copy_rest(sink, start_at);
}
// copy the contents to the given output iterator
template <typename OutputIterator_>
bool buffer_copy_to(OutputIterator_& sink
, std::size_t maxwidth = std::size_t(-1)) const
{
return buffer_data.copy(sink, maxwidth);
}
private:
OutputIterator& sink;
buffer_sink buffer_data; // for buffering
buffer_sink* prev_buffer; // previous buffer in chain
bool enabled;
};
///////////////////////////////////////////////////////////////////////////
// Helper class for exception safe disabling of output
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator>
struct disable_output
{
disable_output(OutputIterator& sink_)
: sink(sink_), prev_do_output(sink.do_output)
{
sink.do_output = false;
}
~disable_output()
{
sink.do_output = prev_do_output;
}
OutputIterator& sink;
bool prev_do_output;
};
///////////////////////////////////////////////////////////////////////////
template <typename Sink>
bool sink_is_good(Sink const&)
{
return true; // the general case is always good
}
template <typename OutputIterator, typename Derived>
bool sink_is_good(output_iterator<OutputIterator, Derived> const& sink)
{
return sink.good(); // our own output iterators are handled separately
}
}}}}
#endif
@@ -0,0 +1,392 @@
/*=============================================================================
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2001-2011 Joel de Guzman
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(SPIRIT_PASS_CONTAINER_MAR_15_2009_0114PM)
#define SPIRIT_PASS_CONTAINER_MAR_15_2009_0114PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/karma/detail/attributes.hpp>
#include <boost/spirit/home/support/container.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/support/detail/hold_any.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/deduce_sequence.hpp>
#include <boost/mpl/print.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
// Helper meta-function allowing to evaluate weak substitutability and
// negate the result if the predicate (Sequence) is not true
template <typename Sequence, typename Attribute, typename ValueType>
struct negate_weak_substitute_if_not
: mpl::if_<
Sequence
, typename traits::is_weak_substitute<Attribute, ValueType>::type
, typename mpl::not_<
traits::is_weak_substitute<Attribute, ValueType>
>::type>
{};
// pass_through_container: utility to check decide whether a provided
// container attribute needs to be passed through to the current component
// or of we need to split the container by passing along instances of its
// value type
// if the expected attribute of the current component is neither a Fusion
// sequence nor a container, we will pass through the provided container
// only if its value type is not compatible with the component
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename Enable = void>
struct pass_through_container_base
: negate_weak_substitute_if_not<Sequence, ValueType, Attribute>
{};
// Specialization for fusion sequences, in this case we check whether all
// the types in the sequence are convertible to the lhs attribute.
//
// We return false if the rhs attribute itself is a fusion sequence, which
// is compatible with the LHS sequence (we want to pass through this
// attribute without it being split apart).
template <typename Container, typename ValueType, typename Attribute
, typename Sequence = mpl::true_>
struct not_compatible_element
: mpl::and_<
negate_weak_substitute_if_not<Sequence, Container, Attribute>
, negate_weak_substitute_if_not<Sequence, ValueType, Attribute> >
{};
// If the value type of the container is not a Fusion sequence, we pass
// through the container if each of the elements of the Attribute
// sequence is compatible with either the container or its value type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
, bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
struct pass_through_container_fusion_sequence
{
typedef typename mpl::find_if<
Attribute, not_compatible_element<Container, ValueType, mpl::_1>
>::type iter;
typedef typename mpl::end<Attribute>::type end;
typedef typename is_same<iter, end>::type type;
};
// If both, the Attribute and the value type of the provided container
// are Fusion sequences, we pass the container only if the two
// sequences are not compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence, true>
{
typedef typename mpl::find_if<
Attribute
, not_compatible_element<Container, ValueType, mpl::_1, Sequence>
>::type iter;
typedef typename mpl::end<Attribute>::type end;
typedef typename is_same<iter, end>::type type;
};
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_base<Container, ValueType, Attribute
, Sequence
, typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
: pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence>
{};
// Specialization for containers
//
// If the value type of the attribute of the current component is not
// a Fusion sequence, we have to pass through the provided container if
// both are compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename AttributeValueType
, bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
struct pass_through_container_container
: mpl::or_<
traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<Container, AttributeValueType> >
{};
// If the value type of the exposed container attribute is a Fusion
// sequence, we use the already existing logic for those.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename AttributeValueType>
struct pass_through_container_container<
Container, ValueType, Attribute, Sequence, AttributeValueType, true>
: pass_through_container_fusion_sequence<
Container, ValueType, AttributeValueType, Sequence>
{};
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_base<Container, ValueType, Attribute
, Sequence
, typename enable_if<traits::is_container<Attribute> >::type>
: detail::pass_through_container_container<
Container, ValueType, Attribute, Sequence
, typename traits::container_value<Attribute>::type>
{};
// Specialization for exposed optional attributes
//
// If the type embedded in the exposed optional is not a Fusion
// sequence we pass through the container attribute if it is compatible
// either to the optionals embedded type or to the containers value
// type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
, bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
struct pass_through_container_optional
: mpl::or_<
traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<ValueType, Attribute> >
{};
// If the embedded type of the exposed optional attribute is a Fusion
// sequence, we use the already existing logic for those.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container_optional<
Container, ValueType, Attribute, Sequence, true>
: pass_through_container_fusion_sequence<
Container, ValueType, Attribute, Sequence>
{};
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container
: pass_through_container_base<Container, ValueType, Attribute, Sequence>
{};
// Handle optional attributes
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, ValueType, boost::optional<Attribute>, Sequence>
: pass_through_container_optional<
Container, ValueType, Attribute, Sequence>
{};
// If both, the containers value type and the exposed attribute type are
// optionals we are allowed to pass through the container only if the
// embedded types of those optionals are not compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, boost::optional<ValueType>, boost::optional<Attribute>
, Sequence>
: mpl::not_<traits::is_weak_substitute<ValueType, Attribute> >
{};
// Specialization for exposed variant attributes
//
// We pass through the container attribute if at least one of the embedded
// types in the variant requires to pass through the attribute
#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
template <typename Container, typename ValueType, typename Sequence
, typename T>
struct pass_through_container<Container, ValueType, boost::variant<T>
, Sequence>
: pass_through_container<Container, ValueType, T, Sequence>
{};
template <typename Container, typename ValueType, typename Sequence
, typename T0, typename ...TN>
struct pass_through_container<Container, ValueType
, boost::variant<T0, TN...>, Sequence>
: mpl::bool_<pass_through_container<
Container, ValueType, T0, Sequence
>::type::value || pass_through_container<
Container, ValueType, boost::variant<TN...>, Sequence
>::type::value>
{};
#else
#define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
pass_through_container<Container, ValueType, \
BOOST_PP_CAT(T, N), Sequence>::type::value || \
/***/
// make sure unused variant parameters do not affect the outcome
template <typename Container, typename ValueType, typename Sequence>
struct pass_through_container<Container, ValueType
, boost::detail::variant::void_, Sequence>
: mpl::false_
{};
template <typename Container, typename ValueType, typename Sequence
, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct pass_through_container<Container, ValueType
, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
: mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
, BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
{};
#undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
#endif
}}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// forwarding customization point for domain karma::domain
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container<
Container, ValueType, Attribute, Sequence, karma::domain>
: karma::detail::pass_through_container<
Container, ValueType, Attribute, Sequence>
{};
}}}
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Iterator>
struct pass_container_base
{
pass_container_base(Iterator begin, Iterator end)
: iter(begin), end(end)
{}
mutable Iterator iter;
mutable Iterator end;
};
template <typename Iterator>
struct pass_container_base<Iterator&>
{
pass_container_base(Iterator& begin, Iterator& end)
: iter(begin), end(end)
{}
Iterator& iter;
Iterator& end;
};
///////////////////////////////////////////////////////////////////////////
// This function handles the case where the attribute (Attr) given
// to the sequence is an STL container. This is a wrapper around F.
// The function F does the actual generating.
template <typename F, typename Attr, typename Iterator, typename Sequence>
struct pass_container : pass_container_base<Iterator>
{
typedef pass_container_base<Iterator> base_type;
typedef typename F::context_type context_type;
pass_container(F const& f, Iterator begin, Iterator end)
: base_type(begin, end)
, f(f)
{}
bool is_at_end() const
{
return traits::compare(this->iter, this->end);
}
void next()
{
traits::next(this->iter);
}
// this is for the case when the current element expects an attribute
// which is taken from the next entry in the container
template <typename Component>
bool dispatch_container(Component const& component, mpl::false_) const
{
// get the next value to generate from container
if (!is_at_end() && !f(component, traits::deref(this->iter)))
{
// needs to return false as long as everything is ok
traits::next(this->iter);
return false;
}
// either no elements available any more or generation failed
return true;
}
// this is for the case when the current element is able to handle an
// attribute which is a container itself, this element will push its
// data directly into the attribute container
template <typename Component>
bool dispatch_container(Component const& component, mpl::true_) const
{
return f(component, make_iterator_range(this->iter, this->end));
}
///////////////////////////////////////////////////////////////////////
// this is for the case when the current element doesn't expect an
// attribute
template <typename Component>
bool dispatch_attribute(Component const& component, mpl::false_) const
{
return f(component, unused);
}
// the current element expects an attribute
template <typename Component>
bool dispatch_attribute(Component const& component, mpl::true_) const
{
typedef typename traits::container_value<Attr>::type value_type;
typedef typename
traits::attribute_of<Component, context_type>::type
lhs_attribute;
// this predicate detects, whether the value type of the container
// attribute is a substitute for the attribute of the current
// element
typedef mpl::and_<
traits::handles_container<Component, Attr, context_type>
, traits::pass_through_container<
Attr, value_type, lhs_attribute, Sequence, karma::domain>
> predicate;
return dispatch_container(component, predicate());
}
// Dispatches to dispatch_main depending on the attribute type
// of the Component
template <typename Component>
bool operator()(Component const& component) const
{
// we need to dispatch depending on the type of the attribute
// of the current element (component). If this is has no attribute
// we shouldn't use an element of the container but unused_type
// instead
typedef traits::not_is_unused<
typename traits::attribute_of<Component, context_type>::type
> predicate;
return dispatch_attribute(component, predicate());
}
F f;
private:
// silence MSVC warning C4512: assignment operator could not be generated
pass_container& operator= (pass_container const&);
};
}}}}
#endif
@@ -0,0 +1,76 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_STRING_COMPARE_AUG_08_2009_0756PM)
#define BOOST_SPIRIT_KARMA_STRING_COMPARE_AUG_08_2009_0756PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <string>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/range/iterator_range.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Char>
bool string_compare(Char const* attr, Char const* lit)
{
Char ch_attr = *attr;
Char ch_lit = *lit;
while (!!ch_lit && !!ch_attr)
{
if (ch_attr != ch_lit)
return false;
ch_attr = *++attr;
ch_lit = *++lit;
}
return !ch_lit && !ch_attr;
}
template <typename Char>
bool string_compare(Char const* attr, Char const* lit, unused_type, unused_type)
{
return string_compare(attr, lit);
}
template <typename Char>
bool string_compare(unused_type, Char const*, unused_type, unused_type)
{
return true;
}
template <typename Char, typename CharEncoding, typename Tag>
bool string_compare(Char const* attr, Char const* lit, CharEncoding, Tag)
{
Char ch_attr = *attr;
Char ch_lit = spirit::char_class::convert<CharEncoding>::to(Tag(), *lit);
while (!!ch_lit && !!ch_attr)
{
if (ch_attr != ch_lit)
return false;
ch_attr = *++attr;
ch_lit = spirit::char_class::convert<CharEncoding>::to(Tag(), *++lit);
}
return !ch_lit && !ch_attr;
}
template <typename Char, typename CharEncoding, typename Tag>
bool string_compare(unused_type, Char const*, CharEncoding, Tag)
{
return true;
}
}}}}
#endif
@@ -0,0 +1,127 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_STRING_GENERATE_FEB_23_2007_1232PM)
#define BOOST_SPIRIT_KARMA_STRING_GENERATE_FEB_23_2007_1232PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <string>
#include <boost/spirit/home/support/char_class.hpp>
#include <boost/spirit/home/karma/detail/generate_to.hpp>
#include <boost/range/const_iterator.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
///////////////////////////////////////////////////////////////////////////
// pass through character transformation
struct pass_through_filter
{
template <typename Char>
Char operator()(Char ch) const
{
return ch;
}
};
template <typename CharEncoding, typename Tag>
struct encoding_filter
{
template <typename Char>
Char operator()(Char ch) const
{
return spirit::char_class::convert<CharEncoding>::to(Tag(), ch);
}
};
///////////////////////////////////////////////////////////////////////////
// generate a string given by a std::string, applying the given filter
template <typename OutputIterator, typename Char, typename Filter>
inline bool string_generate(OutputIterator& sink, Char const* str
, Filter filter)
{
for (Char ch = *str; ch != 0; ch = *++str)
{
*sink = filter(ch);
++sink;
}
return detail::sink_is_good(sink);
}
template <typename OutputIterator, typename Container, typename Filter>
inline bool string_generate(OutputIterator& sink
, Container const& c, Filter filter)
{
typedef typename traits::container_iterator<Container const>::type
iterator;
const iterator end = boost::end(c);
for (iterator it = boost::begin(c); it != end; ++it)
{
*sink = filter(*it);
++sink;
}
return detail::sink_is_good(sink);
}
///////////////////////////////////////////////////////////////////////////
// generate a string without any transformation
template <typename OutputIterator, typename Char>
inline bool string_generate(OutputIterator& sink, Char const* str)
{
return string_generate(sink, str, pass_through_filter());
}
template <typename OutputIterator, typename Container>
inline bool string_generate(OutputIterator& sink
, Container const& c)
{
return string_generate(sink, c, pass_through_filter());
}
///////////////////////////////////////////////////////////////////////////
// generate a string given by a pointer, converting according using a
// given character class and case tag
template <typename OutputIterator, typename Char, typename CharEncoding
, typename Tag>
inline bool string_generate(OutputIterator& sink
, Char const* str
, CharEncoding, Tag)
{
return string_generate(sink, str, encoding_filter<CharEncoding, Tag>());
}
template <typename OutputIterator, typename Container
, typename CharEncoding, typename Tag>
inline bool
string_generate(OutputIterator& sink
, Container const& c
, CharEncoding, Tag)
{
return string_generate(sink, c, encoding_filter<CharEncoding, Tag>());
}
///////////////////////////////////////////////////////////////////////////
template <typename OutputIterator, typename Char>
inline bool string_generate(OutputIterator& sink
, Char const* str
, unused_type, unused_type)
{
return string_generate(sink, str);
}
template <typename OutputIterator, typename Container>
inline bool string_generate(OutputIterator& sink
, Container const& c
, unused_type, unused_type)
{
return string_generate(sink, c);
}
}}}}
#endif
@@ -0,0 +1,51 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_SPIRIT_KARMA_UNUSED_DELIMITER_MAR_15_2009_0923PM)
#define BOOST_SPIRIT_KARMA_UNUSED_DELIMITER_MAR_15_2009_0923PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
namespace boost { namespace spirit { namespace karma { namespace detail
{
template <typename Delimiter>
struct unused_delimiter : unused_type
{
unused_delimiter(Delimiter const& delim)
: delimiter(delim) {}
Delimiter const& delimiter;
private:
// silence MSVC warning C4512: assignment operator could not be generated
unused_delimiter& operator= (unused_delimiter const&);
};
// If a surrounding verbatim[] directive was specified, the current
// delimiter is of the type unused_delimiter. In this case we
// re-activate the delimiter which was active before the verbatim[]
// directive.
template <typename Delimiter, typename Default>
inline Delimiter const&
get_delimiter(unused_delimiter<Delimiter> const& u, Default const&)
{
return u.delimiter;
}
// If no surrounding verbatim[] directive was specified we activate
// a single space as the delimiter to use.
template <typename Delimiter, typename Default>
inline Default const&
get_delimiter(Delimiter const&, Default const& d)
{
return d;
}
}}}}
#endif