size_of.hpp
1 // Copyright (c) 2015 Damien Buhl (alias daminetreg)
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 #ifndef PRE_SPIRIT_KARMA_SIZE_OF_HPP
7 #define PRE_SPIRIT_KARMA_SIZE_OF_HPP
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <boost/spirit/home/karma/meta_compiler.hpp>
14 #include <boost/spirit/home/karma/generator.hpp>
15 #include <boost/spirit/home/karma/domain.hpp>
16 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
17 #include <boost/spirit/home/support/unused.hpp>
18 #include <boost/spirit/home/support/info.hpp>
19 #include <boost/spirit/home/support/common_terminals.hpp>
20 #include <boost/spirit/home/support/has_semantic_action.hpp>
21 #include <boost/spirit/home/support/handles_container.hpp>
22 #include <boost/spirit/home/karma/detail/attributes.hpp>
23 
24 #include <boost/fusion/include/vector.hpp>
25 
26 #include <string>
27 
29 // definition the place holder
30 namespace pre { namespace spirit { namespace karma {
31  namespace mpl = boost::mpl;
32  namespace fusion = boost::fusion;
33 
34  BOOST_SPIRIT_TERMINAL_EX(size_of);
35 
36 }}}
37 
38 namespace boost { namespace spirit {
40  // Enablers
42 
43  template <typename T>
44  struct use_directive<karma::domain
45  , terminal_ex<pre::spirit::karma::tag::size_of // enables size_of(boost::ref(size))[p]
46  , fusion::vector1<T> >
47  > : mpl::true_ {};
48 
49 }}
50 
51 namespace pre { namespace spirit { namespace karma {
52 
53  namespace mpl = boost::mpl;
54 
55  using boost::spirit::buffer_type;
56 
58  // sizeof_directive discards all generated output of the embedded generator
59  // and only give out the size that would have been generated.
61  template <typename Subject>
62  struct sizeof_directive : boost::spirit::karma::unary_generator<sizeof_directive<Subject> >
63  {
64  typedef Subject subject_type;
65  typedef mpl::int_<
66  subject_type::properties::value |
67  boost::spirit::karma::generator_properties::countingbuffer
68  > properties;
69 
70  sizeof_directive(Subject const& subject, std::size_t& size)
71  : subject(subject), size(size) {}
72 
73  template <typename Context, typename Iterator>
74  struct attribute
75  : boost::spirit::traits::attribute_of<subject_type, Context, Iterator>
76  {};
77 
78  template <typename OutputIterator, typename Context, typename Delimiter
79  , typename Attribute>
80  bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
81  , Attribute const& attr_param) const
82  {
83  // wrap the given output iterator to compute size of output
84  boost::spirit::karma::detail::enable_buffering<OutputIterator> buffering(sink);
85  boost::spirit::karma::detail::enable_counting<OutputIterator> counting(sink);
86 
87  bool r = subject.generate(sink, ctx, d, attr_param);
88  size = buffering.buffer_size();
89  return r;
90  }
91 
92  template <typename Context>
93  boost::spirit::info what(Context& context) const
94  {
95  return info("size_of", subject.what(context));
96  }
97 
98  Subject subject;
99  std::size_t& size;
100  };
101 }}}
102 
103 
104 namespace boost { namespace spirit { namespace karma {
105 
107  // Generator generators: make_xxx function (objects)
109  template <typename T, typename Subject, typename Modifiers>
110  struct make_directive<
111  terminal_ex<pre::spirit::karma::tag::size_of, fusion::vector1<T> >,
112  Subject, Modifiers>
113  {
115 
116  template <typename Terminal>
117  result_type operator()(Terminal & term, Subject const& subject
118  , unused_type) const
119  {
120  return result_type(subject, fusion::at_c<0>(term.args));
121  }
122  };
123 
124 }}}
125 
126 namespace boost { namespace spirit { namespace traits
127 {
129  template <typename Subject>
130  struct has_semantic_action<pre::spirit::karma::sizeof_directive<Subject> >
131  : unary_has_semantic_action<Subject> {};
132 
134  template <typename Subject, typename Attribute, typename Context
135  , typename Iterator>
136  struct handles_container<pre::spirit::karma::sizeof_directive<Subject>, Attribute
137  , Context, Iterator>
138  : unary_handles_container<Subject, Attribute, Context, Iterator> {};
139 }}}
140 
141 #endif
Definition: size_of.hpp:62