]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/xpressive/detail/core/matcher/lookbehind_matcher.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / xpressive / detail / core / matcher / lookbehind_matcher.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // lookbehind_matcher.hpp
3 //
4 // Copyright 2008 Eric Niebler. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
9 #define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_LOOKBEHIND_MATCHER_HPP_EAN_10_04_2005
10
11 // MS compatible compilers support #pragma once
12 #if defined(_MSC_VER)
13 # pragma once
14 #endif
15
16 #include <boost/assert.hpp>
17 #include <boost/xpressive/regex_error.hpp>
18 #include <boost/xpressive/regex_constants.hpp>
19 #include <boost/xpressive/detail/detail_fwd.hpp>
20 #include <boost/xpressive/detail/core/quant_style.hpp>
21 #include <boost/xpressive/detail/core/state.hpp>
22 #include <boost/xpressive/detail/utility/algorithm.hpp>
23 #include <boost/xpressive/detail/utility/save_restore.hpp>
24 #include <boost/xpressive/detail/utility/ignore_unused.hpp>
25
26 namespace boost { namespace xpressive { namespace detail
27 {
28
29 ///////////////////////////////////////////////////////////////////////////////
30 // lookbehind_matcher
31 // Xpr can be either a static_xpression or a shared_matchable
32 template<typename Xpr>
33 struct lookbehind_matcher
34 : quant_style<quant_none, 0, Xpr::pure>
35 {
36 lookbehind_matcher(Xpr const &xpr, std::size_t wid, bool no, bool pure = Xpr::pure)
37 : xpr_(xpr)
38 , not_(no)
39 , pure_(pure)
40 , width_(wid)
41 {
42 BOOST_XPR_ENSURE_(!is_unknown(this->width_), regex_constants::error_badlookbehind,
43 "Variable-width look-behind assertions are not supported");
44 }
45
46 void inverse()
47 {
48 this->not_ = !this->not_;
49 }
50
51 template<typename BidiIter, typename Next>
52 bool match(match_state<BidiIter> &state, Next const &next) const
53 {
54 return Xpr::pure || this->pure_
55 ? this->match_(state, next, mpl::true_())
56 : this->match_(state, next, mpl::false_());
57 }
58
59 template<typename BidiIter, typename Next>
60 bool match_(match_state<BidiIter> &state, Next const &next, mpl::true_) const
61 {
62 typedef typename iterator_difference<BidiIter>::type difference_type;
63 BidiIter const tmp = state.cur_;
64 if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
65 {
66 state.cur_ = tmp;
67 return this->not_ ? next.match(state) : false;
68 }
69
70 if(this->not_)
71 {
72 if(this->xpr_.match(state))
73 {
74 BOOST_ASSERT(state.cur_ == tmp);
75 return false;
76 }
77 state.cur_ = tmp;
78 if(next.match(state))
79 {
80 return true;
81 }
82 }
83 else
84 {
85 if(!this->xpr_.match(state))
86 {
87 state.cur_ = tmp;
88 return false;
89 }
90 BOOST_ASSERT(state.cur_ == tmp);
91 if(next.match(state))
92 {
93 return true;
94 }
95 }
96
97 BOOST_ASSERT(state.cur_ == tmp);
98 return false;
99 }
100
101 template<typename BidiIter, typename Next>
102 bool match_(match_state<BidiIter> &state, Next const &next, mpl::false_) const
103 {
104 typedef typename iterator_difference<BidiIter>::type difference_type;
105 BidiIter const tmp = state.cur_;
106 if(!detail::advance_to(state.cur_, -static_cast<difference_type>(this->width_), state.begin_))
107 {
108 state.cur_ = tmp;
109 return this->not_ ? next.match(state) : false;
110 }
111
112 // matching xpr could produce side-effects, save state
113 memento<BidiIter> mem = save_sub_matches(state);
114
115 if(this->not_)
116 {
117 // negative look-ahead assertions do not trigger partial matches.
118 save_restore<bool> partial_match(state.found_partial_match_);
119 detail::ignore_unused(partial_match);
120
121 if(this->xpr_.match(state))
122 {
123 restore_action_queue(mem, state);
124 restore_sub_matches(mem, state);
125 BOOST_ASSERT(state.cur_ == tmp);
126 return false;
127 }
128 state.cur_ = tmp;
129 restore_action_queue(mem, state);
130 if(next.match(state))
131 {
132 reclaim_sub_matches(mem, state, true);
133 return true;
134 }
135 reclaim_sub_matches(mem, state, false);
136 }
137 else
138 {
139 if(!this->xpr_.match(state))
140 {
141 state.cur_ = tmp;
142 restore_action_queue(mem, state);
143 reclaim_sub_matches(mem, state, false);
144 return false;
145 }
146 BOOST_ASSERT(state.cur_ == tmp);
147 restore_action_queue(mem, state);
148 if(next.match(state))
149 {
150 reclaim_sub_matches(mem, state, true);
151 return true;
152 }
153 restore_sub_matches(mem, state);
154 }
155
156 BOOST_ASSERT(state.cur_ == tmp);
157 return false;
158 }
159
160 Xpr xpr_;
161 bool not_;
162 bool pure_; // false if matching xpr_ could modify the sub-matches
163 std::size_t width_;
164 };
165
166 }}}
167
168 #endif