// 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 /////////////////////////////////////////////////////////////////////////////// // 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 : 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 struct columns_delimiter { columns_delimiter(Delimiter const& delim) : delimiter(delim), count(0) {} // This function is called during the actual delimiter output template 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 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 struct simple_columns_generator : boost::spirit::karma::unary_generator< simple_columns_generator > { // Define required output iterator properties typedef typename Subject::properties properties; // Define the attribute type exposed by this parser component template struct attribute : boost::spirit::traits::attribute_of {}; 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 bool generate(OutputIterator& sink, Context& ctx , Delimiter const& delimiter, Attribute const& attr) const { columns_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 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 struct make_directive { typedef custom_generator::simple_columns_generator result_type; result_type operator()(unused_type, Subject const& s, unused_type) const { return result_type(s); } }; }}} #endif