Chris@16
|
1 /*=============================================================================
|
Chris@16
|
2 Copyright (c) 2001-2003 Joel de Guzman
|
Chris@16
|
3 http://spirit.sourceforge.net/
|
Chris@16
|
4
|
Chris@16
|
5 Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 =============================================================================*/
|
Chris@16
|
9 #ifndef BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
|
Chris@16
|
10 #define BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
|
Chris@16
|
11
|
Chris@16
|
12 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
13 #include <algorithm> // for std::lower_bound
|
Chris@16
|
14 #include <boost/limits.hpp>
|
Chris@16
|
15 #include <boost/assert.hpp>
|
Chris@16
|
16 #include <boost/xpressive/detail/utility/chset/range_run.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
19 namespace boost { namespace xpressive { namespace detail
|
Chris@16
|
20 {
|
Chris@16
|
21
|
Chris@16
|
22 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
23 //
|
Chris@16
|
24 // range class implementation
|
Chris@16
|
25 //
|
Chris@16
|
26 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
27 template<typename Char>
|
Chris@16
|
28 inline range<Char>::range(Char first, Char last)
|
Chris@16
|
29 : first_(first)
|
Chris@16
|
30 , last_(last)
|
Chris@16
|
31 {
|
Chris@16
|
32 }
|
Chris@16
|
33
|
Chris@16
|
34 //////////////////////////////////
|
Chris@16
|
35 template<typename Char>
|
Chris@16
|
36 inline bool range<Char>::is_valid() const
|
Chris@16
|
37 {
|
Chris@16
|
38 return this->first_ <= this->last_;
|
Chris@16
|
39 }
|
Chris@16
|
40
|
Chris@16
|
41 //////////////////////////////////
|
Chris@16
|
42 template<typename Char>
|
Chris@16
|
43 inline bool range<Char>::includes(range<Char> const &r) const
|
Chris@16
|
44 {
|
Chris@16
|
45 return (this->first_ <= r.first_) && (this->last_ >= r.last_);
|
Chris@16
|
46 }
|
Chris@16
|
47
|
Chris@16
|
48 //////////////////////////////////
|
Chris@16
|
49 template<typename Char>
|
Chris@16
|
50 inline bool range<Char>::includes(Char v) const
|
Chris@16
|
51 {
|
Chris@16
|
52 return (this->first_ <= v) && (this->last_ >= v);
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 //////////////////////////////////
|
Chris@16
|
56 template<typename Char>
|
Chris@16
|
57 inline bool range<Char>::overlaps(range<Char> const &r) const
|
Chris@16
|
58 {
|
Chris@16
|
59 Char decr_first = (std::min)(this->first_, Char(this->first_-1));
|
Chris@16
|
60 Char incr_last = (std::max)(this->last_, Char(this->last_+1));
|
Chris@16
|
61
|
Chris@16
|
62 return (decr_first <= r.last_) && (incr_last >= r.first_);
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 //////////////////////////////////
|
Chris@16
|
66 template<typename Char>
|
Chris@16
|
67 inline void range<Char>::merge(range<Char> const &r)
|
Chris@16
|
68 {
|
Chris@16
|
69 this->first_ = (std::min)(this->first_, r.first_);
|
Chris@16
|
70 this->last_ = (std::max)(this->last_, r.last_);
|
Chris@16
|
71 }
|
Chris@16
|
72
|
Chris@16
|
73 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
74 //
|
Chris@16
|
75 // range_run class implementation
|
Chris@16
|
76 //
|
Chris@16
|
77 ///////////////////////////////////////////////////////////////////////
|
Chris@16
|
78 template<typename Char>
|
Chris@16
|
79 inline bool range_run<Char>::empty() const
|
Chris@16
|
80 {
|
Chris@16
|
81 return this->run_.empty();
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 template<typename Char>
|
Chris@16
|
85 inline bool range_run<Char>::test(Char v) const
|
Chris@16
|
86 {
|
Chris@16
|
87 if(this->run_.empty())
|
Chris@16
|
88 {
|
Chris@16
|
89 return false;
|
Chris@16
|
90 }
|
Chris@16
|
91
|
Chris@16
|
92 const_iterator iter = std::lower_bound(
|
Chris@16
|
93 this->run_.begin()
|
Chris@16
|
94 , this->run_.end()
|
Chris@16
|
95 , range<Char>(v, v)
|
Chris@16
|
96 , range_compare<Char>()
|
Chris@16
|
97 );
|
Chris@16
|
98
|
Chris@16
|
99 return (iter != this->run_.end() && iter->includes(v))
|
Chris@16
|
100 || (iter != this->run_.begin() && (--iter)->includes(v));
|
Chris@16
|
101 }
|
Chris@16
|
102
|
Chris@16
|
103 template<typename Char>
|
Chris@16
|
104 template<typename Traits>
|
Chris@16
|
105 inline bool range_run<Char>::test(Char v, Traits const &tr) const
|
Chris@16
|
106 {
|
Chris@16
|
107 const_iterator begin = this->run_.begin();
|
Chris@16
|
108 const_iterator end = this->run_.end();
|
Chris@16
|
109
|
Chris@16
|
110 for(; begin != end; ++begin)
|
Chris@16
|
111 {
|
Chris@16
|
112 if(tr.in_range_nocase(begin->first_, begin->last_, v))
|
Chris@16
|
113 {
|
Chris@16
|
114 return true;
|
Chris@16
|
115 }
|
Chris@16
|
116 }
|
Chris@16
|
117 return false;
|
Chris@16
|
118 }
|
Chris@16
|
119
|
Chris@16
|
120 //////////////////////////////////
|
Chris@16
|
121 template<typename Char>
|
Chris@16
|
122 inline void range_run<Char>::swap(range_run<Char> &rr)
|
Chris@16
|
123 {
|
Chris@16
|
124 this->run_.swap(rr.run_);
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 //////////////////////////////////
|
Chris@16
|
128 template<typename Char>
|
Chris@16
|
129 void range_run<Char>::merge(iterator iter, range<Char> const &r)
|
Chris@16
|
130 {
|
Chris@16
|
131 BOOST_ASSERT(iter != this->run_.end());
|
Chris@16
|
132 iter->merge(r);
|
Chris@16
|
133
|
Chris@16
|
134 iterator i = iter;
|
Chris@16
|
135 while(++i != this->run_.end() && iter->overlaps(*i))
|
Chris@16
|
136 {
|
Chris@16
|
137 iter->merge(*i);
|
Chris@16
|
138 }
|
Chris@16
|
139
|
Chris@16
|
140 this->run_.erase(++iter, i);
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 //////////////////////////////////
|
Chris@16
|
144 template<typename Char>
|
Chris@16
|
145 void range_run<Char>::set(range<Char> const &r)
|
Chris@16
|
146 {
|
Chris@16
|
147 BOOST_ASSERT(r.is_valid());
|
Chris@16
|
148 if(!this->run_.empty())
|
Chris@16
|
149 {
|
Chris@16
|
150 iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
|
Chris@16
|
151
|
Chris@16
|
152 if((iter != this->run_.end() && iter->includes(r)) ||
|
Chris@16
|
153 (iter != this->run_.begin() && (iter - 1)->includes(r)))
|
Chris@16
|
154 {
|
Chris@16
|
155 return;
|
Chris@16
|
156 }
|
Chris@16
|
157 else if(iter != this->run_.begin() && (iter - 1)->overlaps(r))
|
Chris@16
|
158 {
|
Chris@16
|
159 this->merge(--iter, r);
|
Chris@16
|
160 }
|
Chris@16
|
161 else if(iter != this->run_.end() && iter->overlaps(r))
|
Chris@16
|
162 {
|
Chris@16
|
163 this->merge(iter, r);
|
Chris@16
|
164 }
|
Chris@16
|
165 else
|
Chris@16
|
166 {
|
Chris@16
|
167 this->run_.insert(iter, r);
|
Chris@16
|
168 }
|
Chris@16
|
169 }
|
Chris@16
|
170 else
|
Chris@16
|
171 {
|
Chris@16
|
172 this->run_.push_back(r);
|
Chris@16
|
173 }
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 //////////////////////////////////
|
Chris@16
|
177 template<typename Char>
|
Chris@16
|
178 void range_run<Char>::clear(range<Char> const &r)
|
Chris@16
|
179 {
|
Chris@16
|
180 BOOST_ASSERT(r.is_valid());
|
Chris@16
|
181 if(!this->run_.empty())
|
Chris@16
|
182 {
|
Chris@16
|
183 iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
|
Chris@16
|
184 iterator left_iter;
|
Chris@16
|
185
|
Chris@16
|
186 if((iter != this->run_.begin()) &&
|
Chris@16
|
187 (left_iter = (iter - 1))->includes(r.first_))
|
Chris@16
|
188 {
|
Chris@16
|
189 if(left_iter->last_ > r.last_)
|
Chris@16
|
190 {
|
Chris@16
|
191 Char save_last = left_iter->last_;
|
Chris@16
|
192 left_iter->last_ = r.first_-1;
|
Chris@16
|
193 this->run_.insert(iter, range<Char>(r.last_+1, save_last));
|
Chris@16
|
194 return;
|
Chris@16
|
195 }
|
Chris@16
|
196 else
|
Chris@16
|
197 {
|
Chris@16
|
198 left_iter->last_ = r.first_-1;
|
Chris@16
|
199 }
|
Chris@16
|
200 }
|
Chris@16
|
201
|
Chris@16
|
202 iterator i = iter;
|
Chris@16
|
203 for(; i != this->run_.end() && r.includes(*i); ++i) {}
|
Chris@16
|
204 if(i != this->run_.end() && i->includes(r.last_))
|
Chris@16
|
205 {
|
Chris@16
|
206 i->first_ = r.last_+1;
|
Chris@16
|
207 }
|
Chris@16
|
208 this->run_.erase(iter, i);
|
Chris@16
|
209 }
|
Chris@16
|
210 }
|
Chris@16
|
211
|
Chris@16
|
212 //////////////////////////////////
|
Chris@16
|
213 template<typename Char>
|
Chris@16
|
214 inline void range_run<Char>::clear()
|
Chris@16
|
215 {
|
Chris@16
|
216 this->run_.clear();
|
Chris@16
|
217 }
|
Chris@16
|
218
|
Chris@16
|
219 //////////////////////////////////
|
Chris@16
|
220 template<typename Char>
|
Chris@16
|
221 inline typename range_run<Char>::const_iterator range_run<Char>::begin() const
|
Chris@16
|
222 {
|
Chris@16
|
223 return this->run_.begin();
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 //////////////////////////////////
|
Chris@16
|
227 template<typename Char>
|
Chris@16
|
228 inline typename range_run<Char>::const_iterator range_run<Char>::end() const
|
Chris@16
|
229 {
|
Chris@16
|
230 return this->run_.end();
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233 }}} // namespace boost::xpressive::detail
|
Chris@16
|
234
|
Chris@16
|
235 #endif
|