crc_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_CRC_OF_HPP
7 #define PRE_SPIRIT_KARMA_CRC_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 <string>
25 #include <boost/crc.hpp>
26 
28 // definition the place holder
29 namespace pre { namespace spirit { namespace karma {
30  BOOST_SPIRIT_TERMINAL_EX(crc_of);
31 }}}
32 
33 namespace boost { namespace spirit {
35  // Enablers
37 
38  template <typename T>
39  struct use_directive<karma::domain
40  , terminal_ex<pre::spirit::karma::tag::crc_of // enables crc_of(boost::ref(crc))[p]
41  , fusion::vector1<T> >
42  > : mpl::true_ {};
43 
44 }}
45 
46 namespace pre { namespace spirit { namespace karma {
47  namespace mpl = boost::mpl;
48 
49  using boost::spirit::buffer_type;
50 
52  // crc_of_directive buffers all generated output of the embedded generator
53  // and flushes it only if the whole embedded generator succeeds
55  template <typename Subject>
56  struct crc_of_directive : boost::spirit::karma::unary_generator<crc_of_directive<Subject> >
57  {
58  typedef Subject subject_type;
59  typedef mpl::int_<
60  subject_type::properties::value |
61  boost::spirit::karma::generator_properties::countingbuffer
62  > properties;
63 
64  crc_of_directive(Subject const& subject, uint16_t& crc)
65  : subject(subject), crc(crc) {}
66 
67  template <typename Context, typename Iterator>
68  struct attribute
69  : boost::spirit::traits::attribute_of<subject_type, Context, Iterator>
70  {};
71 
72  template <typename OutputIterator, typename Context, typename Delimiter
73  , typename Attribute>
74  bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
75  , Attribute const& attr) const
76  {
77  // wrap the given output iterator to compute crc on output
78  boost::spirit::karma::detail::enable_buffering<OutputIterator> buffering(sink);
79  boost::spirit::karma::detail::enable_counting<OutputIterator> counting(sink);
80  bool r = subject.generate(sink, ctx, d, attr);
81 
82  std::string buffered_data;
83  std::back_insert_iterator<std::string> crc_sink(buffered_data);
84  buffering.buffer_copy_to(crc_sink);
85 
86  boost::crc_ccitt_type crc_ccitt;
87  crc_ccitt.reset();
88  crc_ccitt.process_bytes(buffered_data.data(), buffered_data.size());
89  crc = crc_ccitt.checksum();
90 
91  buffering.buffer_copy();
92  return r;
93  }
94 
95  template <typename Context>
96  boost::spirit::info what(Context& context) const
97  {
98  return info("crc_of", subject.what(context));
99  }
100 
101  Subject subject;
102  uint16_t& crc;
103  };
104 }}}
105 
106 
107 namespace boost { namespace spirit { namespace karma {
108 
110  // Generator generators: make_xxx function (objects)
112  template <typename T, typename Subject, typename Modifiers>
113  struct make_directive<
114  terminal_ex<pre::spirit::karma::tag::crc_of, fusion::vector1<T> >,
115  Subject, Modifiers>
116  {
118 
119  template <typename Terminal>
120  result_type operator()(Terminal & term, Subject const& subject
121  , unused_type) const
122  {
123  return result_type(subject, fusion::at_c<0>(term.args));
124  }
125  };
126 
127 }}}
128 
129 namespace boost { namespace spirit { namespace traits
130 {
132  template <typename Subject>
133  struct has_semantic_action<pre::spirit::karma::crc_of_directive<Subject> >
134  : unary_has_semantic_action<Subject> {};
135 
137  template <typename Subject, typename Attribute, typename Context
138  , typename Iterator>
139  struct handles_container<pre::spirit::karma::crc_of_directive<Subject>, Attribute
140  , Context, Iterator>
141  : unary_handles_container<Subject, Attribute, Context, Iterator> {};
142 }}}
143 
144 #endif
Definition: crc_of.hpp:56