1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM)
7 #define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <iterator>
14 #include <string>
15 #include <boost/spirit/home/karma/generate.hpp>
16 #include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
17 #include <boost/mpl/bool.hpp>
18 
19 ///////////////////////////////////////////////////////////////////////////////
20 namespace boost { namespace spirit { namespace karma { namespace detail
21 {
22     ///////////////////////////////////////////////////////////////////////////
23     template <typename Expr
24       , typename CopyExpr = mpl::false_, typename CopyAttr = mpl::false_
25       , typename Delimiter = unused_type, typename Attribute = unused_type>
26     struct format_manip
27     {
28         // This assertion makes sure we don't hit the only code path which is
29         // not implemented (because it isn't needed), where both, the
30         // expression and the attribute need to be held as a copy.
31         BOOST_SPIRIT_ASSERT_MSG(!CopyExpr::value || !CopyAttr::value
32             , error_invalid_should_not_happen, ());
33 
format_manipboost::spirit::karma::detail::format_manip34         format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
35           : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
36 
format_manipboost::spirit::karma::detail::format_manip37         format_manip(Expr const& xpr, Delimiter const& d
38             , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
39           : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
40 
41         Expr const& expr;
42         Delimiter const& delim;
43         BOOST_SCOPED_ENUM(delimit_flag) const pre;
44         Attribute const& attr;
45 
46         // silence MSVC warning C4512: assignment operator could not be generated
47         BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
48     };
49 
50     template <typename Expr, typename Delimiter, typename Attribute>
51     struct format_manip<Expr, mpl::false_, mpl::true_, Delimiter, Attribute>
52     {
format_manipboost::spirit::karma::detail::format_manip53         format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
54           : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
55 
format_manipboost::spirit::karma::detail::format_manip56         format_manip(Expr const& xpr, Delimiter const& d
57             , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
58           : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
59 
60         Expr const& expr;
61         Delimiter const& delim;
62         BOOST_SCOPED_ENUM(delimit_flag) const pre;
63         Attribute attr;
64 
65         // silence MSVC warning C4512: assignment operator could not be generated
66         BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
67     };
68 
69     template <typename Expr, typename Delimiter, typename Attribute>
70     struct format_manip<Expr, mpl::true_, mpl::false_, Delimiter, Attribute>
71     {
format_manipboost::spirit::karma::detail::format_manip72         format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
73           : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
74 
format_manipboost::spirit::karma::detail::format_manip75         format_manip(Expr const& xpr, Delimiter const& d
76             , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
77           : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
78 
79         Expr expr;
80         Delimiter const& delim;
81         BOOST_SCOPED_ENUM(delimit_flag) const pre;
82         Attribute const& attr;
83 
84         // silence MSVC warning C4512: assignment operator could not be generated
85         BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
86     };
87 
88     ///////////////////////////////////////////////////////////////////////////
89     template <typename Expr, typename Enable = void>
90     struct format
91     {
92         // Report invalid expression error as early as possible.
93         // If you got an error_invalid_expression error message here,
94         // then the expression (Expr) is not a valid spirit karma expression.
95         // Did you intend to use the auto_ facilities while forgetting to
96         // #include <boost/spirit/include/karma_format_auto.hpp>?
97         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
98     };
99 
100     template <typename Expr>
101     struct format<Expr
102       , typename enable_if<traits::matches<karma::domain, Expr> >::type>
103     {
104         typedef format_manip<Expr> type;
105 
callboost::spirit::karma::detail::format106         static type call(Expr const& expr)
107         {
108             return type(expr, unused, unused);
109         }
110     };
111 
112     ///////////////////////////////////////////////////////////////////////////
113     template <typename Expr, typename Delimiter, typename Enable = void>
114     struct format_delimited
115     {
116         // Report invalid expression error as early as possible.
117         // If you got an error_invalid_expression error message here,
118         // then the expression (Expr) is not a valid spirit karma expression.
119         // Did you intend to use the auto_ facilities while forgetting to
120         // #include <boost/spirit/include/karma_format_auto.hpp>?
121         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
122     };
123 
124     template <typename Expr, typename Delimiter>
125     struct format_delimited<Expr, Delimiter
126       , typename enable_if<traits::matches<karma::domain, Expr> >::type>
127     {
128         typedef format_manip<Expr, mpl::false_, mpl::false_, Delimiter> type;
129 
callboost::spirit::karma::detail::format_delimited130         static type call(
131             Expr const& expr
132           , Delimiter const& delimiter
133           , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
134         {
135             // Report invalid expression error as early as possible.
136             // If you got an error_invalid_expression error message here,
137             // then the delimiter is not a valid spirit karma expression.
138             BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
139             return type(expr, delimiter, pre_delimit, unused);
140         }
141     };
142 
143     ///////////////////////////////////////////////////////////////////////////
144     template<typename Char, typename Traits, typename Expr
145       , typename CopyExpr, typename CopyAttr>
146     inline std::basic_ostream<Char, Traits> &
operator <<(std::basic_ostream<Char,Traits> & os,format_manip<Expr,CopyExpr,CopyAttr> const & fm)147     operator<< (std::basic_ostream<Char, Traits> &os
148       , format_manip<Expr, CopyExpr, CopyAttr> const& fm)
149     {
150         karma::ostream_iterator<Char, Char, Traits> sink(os);
151         if (!karma::generate (sink, fm.expr))
152         {
153             os.setstate(std::ios_base::failbit);
154         }
155         return os;
156     }
157 
158     ///////////////////////////////////////////////////////////////////////////
159     template<typename Char, typename Traits, typename Expr
160       , typename CopyExpr, typename CopyAttr, typename Attribute>
161     inline std::basic_ostream<Char, Traits> &
operator <<(std::basic_ostream<Char,Traits> & os,format_manip<Expr,CopyExpr,CopyAttr,unused_type,Attribute> const & fm)162     operator<< (std::basic_ostream<Char, Traits> &os
163       , format_manip<Expr, CopyExpr, CopyAttr, unused_type, Attribute> const& fm)
164     {
165         karma::ostream_iterator<Char, Char, Traits> sink(os);
166         if (!karma::generate(sink, fm.expr, fm.attr))
167         {
168             os.setstate(std::ios_base::failbit);
169         }
170         return os;
171     }
172 
173     template<typename Char, typename Traits, typename Expr
174       , typename CopyExpr, typename CopyAttr, typename Delimiter>
175     inline std::basic_ostream<Char, Traits> &
operator <<(std::basic_ostream<Char,Traits> & os,format_manip<Expr,CopyExpr,CopyAttr,Delimiter> const & fm)176     operator<< (std::basic_ostream<Char, Traits> &os
177       , format_manip<Expr, CopyExpr, CopyAttr, Delimiter> const& fm)
178     {
179         karma::ostream_iterator<Char, Char, Traits> sink(os);
180         if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre))
181         {
182             os.setstate(std::ios_base::failbit);
183         }
184         return os;
185     }
186 
187     ///////////////////////////////////////////////////////////////////////////
188     template<typename Char, typename Traits, typename Expr
189       , typename CopyExpr, typename CopyAttr, typename Delimiter
190       , typename Attribute>
191     inline std::basic_ostream<Char, Traits> &
operator <<(std::basic_ostream<Char,Traits> & os,format_manip<Expr,CopyExpr,CopyAttr,Delimiter,Attribute> const & fm)192     operator<< (std::basic_ostream<Char, Traits> &os
193       , format_manip<Expr, CopyExpr, CopyAttr, Delimiter, Attribute> const& fm)
194     {
195         karma::ostream_iterator<Char, Char, Traits> sink(os);
196         if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre, fm.attr))
197         {
198             os.setstate(std::ios_base::failbit);
199         }
200         return os;
201     }
202 }}}}
203 
204 #endif
205