]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/repository/home/qi/primitive/advance.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / repository / home / qi / primitive / advance.hpp
1 // Copyright (c) 2011 Aaron Graham
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_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM)
7 #define BOOST_SPIRIT_REPOSITORY_QI_ADVANCE_JAN_23_2011_1203PM
8
9 #include <boost/spirit/include/qi_parse.hpp>
10
11 ///////////////////////////////////////////////////////////////////////////////
12 // definition the place holder
13 namespace boost { namespace spirit { namespace repository { namespace qi
14 {
15 BOOST_SPIRIT_TERMINAL_EX(advance);
16 }}}}
17
18 ///////////////////////////////////////////////////////////////////////////////
19 // implementation the enabler
20 namespace boost { namespace spirit
21 {
22 template <typename A0>
23 struct use_terminal<qi::domain
24 , terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> > >
25 : mpl::or_<is_integral<A0>, is_enum<A0> >
26 {};
27
28 template <>
29 struct use_lazy_terminal<qi::domain, repository::qi::tag::advance, 1>
30 : mpl::true_
31 {};
32 }}
33
34 ///////////////////////////////////////////////////////////////////////////////
35 // implementation of the parser
36 namespace boost { namespace spirit { namespace repository { namespace qi
37 {
38 template <typename Int>
39 struct advance_parser
40 : boost::spirit::qi::primitive_parser< advance_parser<Int> >
41 {
42 // Define the attribute type exposed by this parser component
43 template <typename Context, typename Iterator>
44 struct attribute
45 {
46 typedef boost::spirit::unused_type type;
47 };
48
49 advance_parser(Int dist)
50 : dist(dist)
51 {}
52
53 // This function is called during the actual parsing process
54 template <typename Iterator, typename Context
55 , typename Skipper, typename Attribute>
56 bool parse(Iterator& first, Iterator const& last
57 , Context&, Skipper&, Attribute&) const
58 {
59 // This series of checks is designed to fail parsing on negative
60 // values, without generating a "expression always evaluates true"
61 // warning on unsigned types.
62 if (dist == Int(0)) return true;
63 if (dist < Int(1)) return false;
64
65 typedef typename std::iterator_traits<Iterator>::iterator_category
66 iterator_category;
67 return advance(first, last, iterator_category());
68 }
69
70 // This function is called during error handling to create
71 // a human readable string for the error context.
72 template <typename Context>
73 boost::spirit::info what(Context&) const
74 {
75 return boost::spirit::info("advance");
76 }
77
78 private:
79 // this is the general implementation used by most iterator categories
80 template <typename Iterator, typename IteratorCategory>
81 bool advance(Iterator& first, Iterator const& last
82 , IteratorCategory) const
83 {
84 Int n = dist;
85 Iterator i = first;
86 while (n)
87 {
88 if (i == last) return false;
89 ++i;
90 --n;
91 }
92 first = i;
93 return true;
94 }
95
96 // this is a specialization for random access iterators
97 template <typename Iterator>
98 bool advance(Iterator& first, Iterator const& last
99 , std::random_access_iterator_tag) const
100 {
101 Iterator const it = first + dist;
102 if (it > last) return false;
103 first = it;
104 return true;
105 }
106
107 Int const dist;
108 };
109 }}}}
110
111 ///////////////////////////////////////////////////////////////////////////////
112 // instantiation of the parser
113 namespace boost { namespace spirit { namespace qi
114 {
115 template <typename Modifiers, typename A0>
116 struct make_primitive<
117 terminal_ex<repository::qi::tag::advance, fusion::vector1<A0> >
118 , Modifiers>
119 {
120 typedef repository::qi::advance_parser<A0> result_type;
121
122 template <typename Terminal>
123 result_type operator()(Terminal const& term, unused_type) const
124 {
125 return result_type(fusion::at_c<0>(term.args));
126 }
127 };
128 }}}
129
130 #endif