134 lines
4.6 KiB
C++
134 lines
4.6 KiB
C++
// Copyright (c) 2001-2010 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(COLUMNS_DEC_05_2009_0716PM)
|
|
#define COLUMNS_DEC_05_2009_0716PM
|
|
|
|
#include <boost/spirit/include/karma_generate.hpp>
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// definition the place holder
|
|
namespace custom_generator
|
|
{
|
|
BOOST_SPIRIT_TERMINAL(columns)
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// implementation the enabler
|
|
namespace boost { namespace spirit
|
|
{
|
|
// We want custom_generator::columns to be usable as a directive only,
|
|
// and only for generator expressions (karma::domain).
|
|
template <>
|
|
struct use_directive<karma::domain, custom_generator::tag::columns>
|
|
: mpl::true_ {};
|
|
}}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// implementation of the generator
|
|
namespace custom_generator
|
|
{
|
|
// special delimiter wrapping the original one while additionally emitting
|
|
// the column delimiter after each 5th invocation
|
|
template <typename Delimiter>
|
|
struct columns_delimiter
|
|
{
|
|
columns_delimiter(Delimiter const& delim)
|
|
: delimiter(delim), count(0) {}
|
|
|
|
// This function is called during the actual delimiter output
|
|
template <typename OutputIterator, typename Context
|
|
, typename Delimiter_, typename Attribute>
|
|
bool generate(OutputIterator& sink, Context&, Delimiter_ const&
|
|
, Attribute const&) const
|
|
{
|
|
// first invoke the wrapped delimiter
|
|
if (!karma::delimit_out(sink, delimiter))
|
|
return false;
|
|
|
|
// now we count the number of invocations and emit the column
|
|
// delimiter after each 5th column
|
|
if ((++count % 5) == 0)
|
|
*sink++ = '\n';
|
|
return true;
|
|
}
|
|
|
|
// Generate a final column delimiter if the last invocation didn't
|
|
// emit one
|
|
template <typename OutputIterator>
|
|
bool final_delimit_out(OutputIterator& sink) const
|
|
{
|
|
if (count % 5)
|
|
*sink++ = '\n';
|
|
return true;
|
|
}
|
|
|
|
Delimiter const& delimiter; // wrapped delimiter
|
|
mutable unsigned int count; // invocation counter
|
|
};
|
|
|
|
// That's the actual columns generator
|
|
template <typename Subject>
|
|
struct simple_columns_generator
|
|
: boost::spirit::karma::unary_generator<
|
|
simple_columns_generator<Subject> >
|
|
{
|
|
// Define required output iterator properties
|
|
typedef typename Subject::properties properties;
|
|
|
|
// Define the attribute type exposed by this parser component
|
|
template <typename Context, typename Iterator>
|
|
struct attribute
|
|
: boost::spirit::traits::attribute_of<Subject, Context, Iterator>
|
|
{};
|
|
|
|
simple_columns_generator(Subject const& s)
|
|
: subject(s)
|
|
{}
|
|
|
|
// This function is called during the actual output generation process.
|
|
// It dispatches to the embedded generator while supplying a new
|
|
// delimiter to use, wrapping the outer delimiter.
|
|
template <typename OutputIterator, typename Context
|
|
, typename Delimiter, typename Attribute>
|
|
bool generate(OutputIterator& sink, Context& ctx
|
|
, Delimiter const& delimiter, Attribute const& attr) const
|
|
{
|
|
columns_delimiter<Delimiter> d(delimiter);
|
|
return subject.generate(sink, ctx, d, attr) && d.final_delimit_out(sink);
|
|
}
|
|
|
|
// This function is called during error handling to create
|
|
// a human readable string for the error context.
|
|
template <typename Context>
|
|
boost::spirit::info what(Context& ctx) const
|
|
{
|
|
return boost::spirit::info("columns", subject.what(ctx));
|
|
}
|
|
|
|
Subject subject;
|
|
};
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// instantiation of the generator
|
|
namespace boost { namespace spirit { namespace karma
|
|
{
|
|
// This is the factory function object invoked in order to create
|
|
// an instance of our simple_columns_generator.
|
|
template <typename Subject, typename Modifiers>
|
|
struct make_directive<custom_generator::tag::columns, Subject, Modifiers>
|
|
{
|
|
typedef custom_generator::simple_columns_generator<Subject> result_type;
|
|
|
|
result_type operator()(unused_type, Subject const& s, unused_type) const
|
|
{
|
|
return result_type(s);
|
|
}
|
|
};
|
|
}}}
|
|
|
|
#endif
|