Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 /// \file match_results.hpp
|
Chris@16
|
3 /// Contains the definition of the match_results type and associated helpers.
|
Chris@16
|
4 /// The match_results type holds the results of a regex_match() or
|
Chris@16
|
5 /// regex_search() operation.
|
Chris@16
|
6 //
|
Chris@16
|
7 // Copyright 2008 Eric Niebler. Distributed under the Boost
|
Chris@16
|
8 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10 //
|
Chris@16
|
11 // Acknowledgements: Thanks to Markus Schoepflin for helping to track down
|
Chris@16
|
12 // a tricky formatting bug on HP Tru64, and to Steven Watanabe for suggesting
|
Chris@16
|
13 // the fix.
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
|
Chris@16
|
16 #define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
|
Chris@16
|
17
|
Chris@16
|
18 // MS compatible compilers support #pragma once
|
Chris@101
|
19 #if defined(_MSC_VER)
|
Chris@16
|
20 # pragma once
|
Chris@16
|
21 #endif
|
Chris@16
|
22
|
Chris@16
|
23 #include <map>
|
Chris@16
|
24 #include <string>
|
Chris@16
|
25 #include <vector>
|
Chris@16
|
26 #include <utility>
|
Chris@16
|
27 #include <iterator>
|
Chris@16
|
28 #include <typeinfo>
|
Chris@16
|
29 #include <algorithm>
|
Chris@16
|
30 #include <boost/config.hpp>
|
Chris@16
|
31 #include <boost/assert.hpp>
|
Chris@16
|
32 #include <boost/integer.hpp>
|
Chris@16
|
33 #include <boost/mpl/if.hpp>
|
Chris@16
|
34 #include <boost/mpl/not.hpp>
|
Chris@16
|
35 #include <boost/mpl/size_t.hpp>
|
Chris@16
|
36 #include <boost/mpl/assert.hpp>
|
Chris@16
|
37 #include <boost/intrusive_ptr.hpp>
|
Chris@16
|
38 #include <boost/throw_exception.hpp>
|
Chris@16
|
39 #include <boost/iterator_adaptors.hpp>
|
Chris@16
|
40 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
41 #include <boost/detail/workaround.hpp>
|
Chris@16
|
42 #include <boost/numeric/conversion/converter.hpp>
|
Chris@16
|
43 #include <boost/optional.hpp>
|
Chris@16
|
44 #include <boost/range/end.hpp>
|
Chris@16
|
45 #include <boost/range/begin.hpp>
|
Chris@16
|
46 #include <boost/range/as_literal.hpp>
|
Chris@16
|
47 #include <boost/range/const_iterator.hpp>
|
Chris@16
|
48 #include <boost/type_traits/is_function.hpp>
|
Chris@16
|
49 #if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
|
Chris@16
|
50 # include <boost/iterator/filter_iterator.hpp>
|
Chris@16
|
51 #endif
|
Chris@16
|
52 #include <boost/xpressive/regex_constants.hpp>
|
Chris@16
|
53 #include <boost/xpressive/detail/detail_fwd.hpp>
|
Chris@16
|
54 #include <boost/xpressive/detail/core/regex_impl.hpp>
|
Chris@16
|
55 #include <boost/xpressive/detail/core/sub_match_vector.hpp>
|
Chris@16
|
56 #include <boost/xpressive/detail/utility/sequence_stack.hpp>
|
Chris@16
|
57 #include <boost/xpressive/detail/core/results_cache.hpp>
|
Chris@16
|
58 #include <boost/xpressive/detail/utility/literals.hpp>
|
Chris@16
|
59 #include <boost/xpressive/detail/utility/algorithm.hpp>
|
Chris@16
|
60 #include <boost/xpressive/detail/utility/counted_base.hpp>
|
Chris@16
|
61 // Doxygen can't handle proto :-(
|
Chris@16
|
62 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
|
Chris@16
|
63 # include <boost/proto/proto_fwd.hpp>
|
Chris@16
|
64 # include <boost/proto/traits.hpp>
|
Chris@16
|
65 #endif
|
Chris@16
|
66
|
Chris@16
|
67 namespace boost { namespace xpressive { namespace detail
|
Chris@16
|
68 {
|
Chris@16
|
69
|
Chris@16
|
70 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
71 // type_info_less
|
Chris@16
|
72 //
|
Chris@16
|
73 struct type_info_less
|
Chris@16
|
74 {
|
Chris@16
|
75 bool operator()(std::type_info const *left, std::type_info const *right) const
|
Chris@16
|
76 {
|
Chris@16
|
77 return 0 != left->before(*right);
|
Chris@16
|
78 }
|
Chris@16
|
79 };
|
Chris@16
|
80
|
Chris@16
|
81 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
82 // ActionArgBinding
|
Chris@16
|
83 //
|
Chris@16
|
84 struct ActionArgBinding
|
Chris@16
|
85 : proto::assign<proto::terminal<action_arg<proto::_, proto::_> >, proto::terminal<proto::_> >
|
Chris@16
|
86 {
|
Chris@16
|
87 };
|
Chris@16
|
88
|
Chris@16
|
89 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
90 // results_extras
|
Chris@16
|
91 //
|
Chris@16
|
92 template<typename BidiIter>
|
Chris@16
|
93 struct results_extras
|
Chris@16
|
94 : counted_base<results_extras<BidiIter> >
|
Chris@16
|
95 {
|
Chris@16
|
96 sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
|
Chris@16
|
97 results_cache<BidiIter> results_cache_;
|
Chris@16
|
98 };
|
Chris@16
|
99
|
Chris@16
|
100 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
101 // char_overflow_handler_
|
Chris@16
|
102 //
|
Chris@16
|
103 struct char_overflow_handler_
|
Chris@16
|
104 {
|
Chris@16
|
105 void operator ()(numeric::range_check_result result) const // throw(regex_error)
|
Chris@16
|
106 {
|
Chris@16
|
107 if(numeric::cInRange != result)
|
Chris@16
|
108 {
|
Chris@16
|
109 BOOST_THROW_EXCEPTION(
|
Chris@16
|
110 regex_error(
|
Chris@16
|
111 regex_constants::error_escape
|
Chris@16
|
112 , "character escape too large to fit in target character type"
|
Chris@16
|
113 )
|
Chris@16
|
114 );
|
Chris@16
|
115 }
|
Chris@16
|
116 }
|
Chris@16
|
117 };
|
Chris@16
|
118
|
Chris@16
|
119 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
120 // transform_op enum
|
Chris@16
|
121 //
|
Chris@16
|
122 enum transform_op { op_none = 0, op_upper = 1, op_lower = 2 };
|
Chris@16
|
123 enum transform_scope { scope_next = 0, scope_rest = 1 };
|
Chris@16
|
124
|
Chris@16
|
125 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
126 // case_converting_iterator
|
Chris@16
|
127 //
|
Chris@16
|
128 template<typename OutputIterator, typename Char>
|
Chris@16
|
129 struct case_converting_iterator
|
Chris@16
|
130 : std::iterator<std::output_iterator_tag, Char, void, void, case_converting_iterator<OutputIterator, Char> >
|
Chris@16
|
131 {
|
Chris@16
|
132 case_converting_iterator(OutputIterator const &out, traits<Char> const *tr)
|
Chris@16
|
133 : out_(out)
|
Chris@16
|
134 , traits_(tr)
|
Chris@16
|
135 , next_(op_none)
|
Chris@16
|
136 , rest_(op_none)
|
Chris@16
|
137 {}
|
Chris@16
|
138
|
Chris@16
|
139 OutputIterator base() const
|
Chris@16
|
140 {
|
Chris@16
|
141 return this->out_;
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 case_converting_iterator &operator ++()
|
Chris@16
|
145 {
|
Chris@16
|
146 ++this->out_;
|
Chris@16
|
147 this->next_ = op_none;
|
Chris@16
|
148 return *this;
|
Chris@16
|
149 }
|
Chris@16
|
150
|
Chris@16
|
151 case_converting_iterator operator ++(int)
|
Chris@16
|
152 {
|
Chris@16
|
153 case_converting_iterator tmp(*this);
|
Chris@16
|
154 ++*this;
|
Chris@16
|
155 return tmp;
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 case_converting_iterator &operator *()
|
Chris@16
|
159 {
|
Chris@16
|
160 return *this;
|
Chris@16
|
161 }
|
Chris@16
|
162
|
Chris@16
|
163 friend bool set_transform(case_converting_iterator &iter, transform_op trans, transform_scope scope)
|
Chris@16
|
164 {
|
Chris@16
|
165 BOOST_ASSERT(scope == scope_next || scope == scope_rest);
|
Chris@16
|
166 if(scope == scope_next)
|
Chris@16
|
167 iter.next_ = trans;
|
Chris@16
|
168 else
|
Chris@16
|
169 iter.rest_ = trans;
|
Chris@16
|
170 return true;
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 case_converting_iterator &operator =(Char ch)
|
Chris@16
|
174 {
|
Chris@16
|
175 switch(this->next_ ? this->next_ : this->rest_)
|
Chris@16
|
176 {
|
Chris@16
|
177 case op_lower:
|
Chris@16
|
178 ch = this->traits_->tolower(ch);
|
Chris@16
|
179 break;
|
Chris@16
|
180
|
Chris@16
|
181 case op_upper:
|
Chris@16
|
182 ch = this->traits_->toupper(ch);
|
Chris@16
|
183 break;
|
Chris@16
|
184
|
Chris@16
|
185 default:;
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 *this->out_ = ch;
|
Chris@16
|
189 return *this;
|
Chris@16
|
190 }
|
Chris@16
|
191
|
Chris@16
|
192 private:
|
Chris@16
|
193 OutputIterator out_;
|
Chris@16
|
194 traits<Char> const *traits_;
|
Chris@16
|
195 transform_op next_, rest_;
|
Chris@16
|
196 };
|
Chris@16
|
197
|
Chris@16
|
198 template<typename Iterator>
|
Chris@16
|
199 inline bool set_transform(Iterator &, transform_op, transform_scope)
|
Chris@16
|
200 {
|
Chris@16
|
201 return false;
|
Chris@16
|
202 }
|
Chris@16
|
203
|
Chris@16
|
204 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
205 // noop_output_iterator
|
Chris@16
|
206 //
|
Chris@16
|
207 template<typename Char>
|
Chris@16
|
208 struct noop_output_iterator
|
Chris@16
|
209 : std::iterator<std::output_iterator_tag, Char, void, void, noop_output_iterator<Char> >
|
Chris@16
|
210 {
|
Chris@16
|
211 noop_output_iterator &operator ++()
|
Chris@16
|
212 {
|
Chris@16
|
213 return *this;
|
Chris@16
|
214 }
|
Chris@16
|
215
|
Chris@16
|
216 noop_output_iterator &operator ++(int)
|
Chris@16
|
217 {
|
Chris@16
|
218 return *this;
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 noop_output_iterator &operator *()
|
Chris@16
|
222 {
|
Chris@16
|
223 return *this;
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 noop_output_iterator &operator =(Char const &)
|
Chris@16
|
227 {
|
Chris@16
|
228 return *this;
|
Chris@16
|
229 }
|
Chris@16
|
230 };
|
Chris@16
|
231
|
Chris@16
|
232 struct any_type { any_type(...); };
|
Chris@16
|
233 typedef char no_type;
|
Chris@16
|
234 typedef char (&unary_type)[2];
|
Chris@16
|
235 typedef char (&binary_type)[3];
|
Chris@16
|
236 typedef char (&ternary_type)[4];
|
Chris@16
|
237
|
Chris@16
|
238 no_type check_is_formatter(unary_type, binary_type, ternary_type);
|
Chris@16
|
239
|
Chris@16
|
240 template<typename T>
|
Chris@16
|
241 unary_type check_is_formatter(T const &, binary_type, ternary_type);
|
Chris@16
|
242
|
Chris@16
|
243 template<typename T>
|
Chris@16
|
244 binary_type check_is_formatter(unary_type, T const &, ternary_type);
|
Chris@16
|
245
|
Chris@16
|
246 template<typename T, typename U>
|
Chris@16
|
247 binary_type check_is_formatter(T const &, U const &, ternary_type);
|
Chris@16
|
248
|
Chris@16
|
249 template<typename T>
|
Chris@16
|
250 ternary_type check_is_formatter(unary_type, binary_type, T const &);
|
Chris@16
|
251
|
Chris@16
|
252 template<typename T, typename U>
|
Chris@16
|
253 ternary_type check_is_formatter(T const &, binary_type, U const &);
|
Chris@16
|
254
|
Chris@16
|
255 template<typename T, typename U>
|
Chris@16
|
256 ternary_type check_is_formatter(unary_type, T const &, U const &);
|
Chris@16
|
257
|
Chris@16
|
258 template<typename T, typename U, typename V>
|
Chris@16
|
259 ternary_type check_is_formatter(T const &, U const &, V const &);
|
Chris@16
|
260
|
Chris@16
|
261 struct unary_binary_ternary
|
Chris@16
|
262 {
|
Chris@16
|
263 typedef unary_type (*unary_fun)(any_type);
|
Chris@16
|
264 typedef binary_type (*binary_fun)(any_type, any_type);
|
Chris@16
|
265 typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
|
Chris@16
|
266 operator unary_fun();
|
Chris@16
|
267 operator binary_fun();
|
Chris@16
|
268 operator ternary_fun();
|
Chris@16
|
269 };
|
Chris@16
|
270
|
Chris@16
|
271 template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
|
Chris@16
|
272 struct formatter_wrapper
|
Chris@16
|
273 : Formatter
|
Chris@16
|
274 , unary_binary_ternary
|
Chris@16
|
275 {
|
Chris@16
|
276 formatter_wrapper();
|
Chris@16
|
277 };
|
Chris@16
|
278
|
Chris@16
|
279 template<typename Formatter>
|
Chris@16
|
280 struct formatter_wrapper<Formatter, true>
|
Chris@16
|
281 : unary_binary_ternary
|
Chris@16
|
282 {
|
Chris@16
|
283 operator Formatter *();
|
Chris@16
|
284 };
|
Chris@16
|
285
|
Chris@16
|
286 template<typename Formatter>
|
Chris@16
|
287 struct formatter_wrapper<Formatter *, false>
|
Chris@16
|
288 : unary_binary_ternary
|
Chris@16
|
289 {
|
Chris@16
|
290 operator Formatter *();
|
Chris@16
|
291 };
|
Chris@16
|
292
|
Chris@16
|
293 template<typename Formatter, typename What, typename Out, typename Void = void>
|
Chris@16
|
294 struct formatter_arity
|
Chris@16
|
295 {
|
Chris@16
|
296 static formatter_wrapper<Formatter> &formatter;
|
Chris@16
|
297 static What &what;
|
Chris@16
|
298 static Out &out;
|
Chris@16
|
299 BOOST_STATIC_CONSTANT(
|
Chris@16
|
300 std::size_t
|
Chris@16
|
301 , value = sizeof(
|
Chris@16
|
302 check_is_formatter(
|
Chris@16
|
303 formatter(what)
|
Chris@16
|
304 , formatter(what, out)
|
Chris@16
|
305 , formatter(what, out, regex_constants::format_default)
|
Chris@16
|
306 )
|
Chris@16
|
307 ) - 1
|
Chris@16
|
308 );
|
Chris@16
|
309 typedef mpl::size_t<value> type;
|
Chris@16
|
310 };
|
Chris@16
|
311
|
Chris@16
|
312 template<typename Formatter, typename What, typename Out>
|
Chris@16
|
313 struct formatter_arity<Formatter, What, Out, typename Formatter::proto_is_expr_>
|
Chris@16
|
314 : mpl::size_t<4>
|
Chris@16
|
315 {};
|
Chris@16
|
316
|
Chris@16
|
317 template<typename T>
|
Chris@16
|
318 struct is_char_ptr
|
Chris@16
|
319 : mpl::false_
|
Chris@16
|
320 {};
|
Chris@16
|
321
|
Chris@16
|
322 template<typename T>
|
Chris@16
|
323 struct is_char_ptr<T *>
|
Chris@16
|
324 : mpl::not_<is_function<T> >
|
Chris@16
|
325 {};
|
Chris@16
|
326
|
Chris@16
|
327 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
|
Chris@16
|
328 // work around gcc-4.0.1 compiler bug wrt function references
|
Chris@16
|
329 template<typename T>
|
Chris@16
|
330 typename mpl::if_<is_function<T>, T *, T const &>::type
|
Chris@16
|
331 as_callable(T const &t)
|
Chris@16
|
332 {
|
Chris@16
|
333 return t;
|
Chris@16
|
334 }
|
Chris@16
|
335 #endif
|
Chris@16
|
336
|
Chris@16
|
337 } // detail
|
Chris@16
|
338
|
Chris@16
|
339 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
340 // match_results
|
Chris@16
|
341 /// \brief Class template match_results\<\> holds the results of a regex_match() or a
|
Chris@16
|
342 /// regex_search() as a collection of sub_match objects.
|
Chris@16
|
343 ///
|
Chris@16
|
344 /// Class template match_results\<\> denotes a collection of sequences representing the result of
|
Chris@16
|
345 /// a regular expression match. Storage for the collection is allocated and freed as necessary by
|
Chris@16
|
346 /// the member functions of class match_results\<\>.
|
Chris@16
|
347 ///
|
Chris@16
|
348 /// The class template match_results\<\> conforms to the requirements of a Sequence, as specified
|
Chris@16
|
349 /// in (lib.sequence.reqmts), except that only operations defined for const-qualified Sequences are
|
Chris@16
|
350 /// supported.
|
Chris@16
|
351 template<typename BidiIter>
|
Chris@16
|
352 struct match_results
|
Chris@16
|
353 {
|
Chris@16
|
354 private:
|
Chris@16
|
355 /// INTERNAL ONLY
|
Chris@16
|
356 ///
|
Chris@16
|
357 struct dummy { int i_; };
|
Chris@16
|
358 typedef int dummy::*bool_type;
|
Chris@16
|
359
|
Chris@16
|
360 public:
|
Chris@16
|
361 typedef typename iterator_value<BidiIter>::type char_type;
|
Chris@16
|
362 typedef typename detail::string_type<char_type>::type string_type;
|
Chris@16
|
363 typedef std::size_t size_type;
|
Chris@16
|
364 typedef sub_match<BidiIter> value_type;
|
Chris@16
|
365 typedef typename iterator_difference<BidiIter>::type difference_type;
|
Chris@16
|
366 typedef value_type const &reference;
|
Chris@16
|
367 typedef value_type const &const_reference;
|
Chris@16
|
368
|
Chris@16
|
369 typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
|
Chris@16
|
370 typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
|
Chris@16
|
371 typedef typename detail::nested_results<BidiIter> nested_results_type;
|
Chris@16
|
372
|
Chris@16
|
373 /// \post regex_id() == 0
|
Chris@16
|
374 /// \post size() == 0
|
Chris@16
|
375 /// \post empty() == true
|
Chris@16
|
376 /// \post str() == string_type()
|
Chris@16
|
377 match_results()
|
Chris@16
|
378 : regex_id_(0)
|
Chris@16
|
379 , sub_matches_()
|
Chris@16
|
380 , base_()
|
Chris@16
|
381 , prefix_()
|
Chris@16
|
382 , suffix_()
|
Chris@16
|
383 , nested_results_()
|
Chris@16
|
384 , extras_ptr_()
|
Chris@16
|
385 , traits_()
|
Chris@16
|
386 , args_()
|
Chris@16
|
387 , named_marks_()
|
Chris@16
|
388 {
|
Chris@16
|
389 }
|
Chris@16
|
390
|
Chris@16
|
391 /// \param that The match_results object to copy
|
Chris@16
|
392 /// \post regex_id() == that.regex_id().
|
Chris@16
|
393 /// \post size() == that.size().
|
Chris@16
|
394 /// \post empty() == that.empty().
|
Chris@16
|
395 /// \post str(n) == that.str(n) for all positive integers n \< that.size().
|
Chris@16
|
396 /// \post prefix() == that.prefix().
|
Chris@16
|
397 /// \post suffix() == that.suffix().
|
Chris@16
|
398 /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
|
Chris@16
|
399 /// \post length(n) == that.length(n) for all positive integers n \< that.size().
|
Chris@16
|
400 /// \post position(n) == that.position(n) for all positive integers n \< that.size().
|
Chris@16
|
401 match_results(match_results<BidiIter> const &that)
|
Chris@16
|
402 : regex_id_(that.regex_id_)
|
Chris@16
|
403 , sub_matches_()
|
Chris@16
|
404 , base_()
|
Chris@16
|
405 , prefix_()
|
Chris@16
|
406 , suffix_()
|
Chris@16
|
407 , nested_results_()
|
Chris@16
|
408 , extras_ptr_()
|
Chris@16
|
409 , traits_()
|
Chris@16
|
410 , args_(that.args_)
|
Chris@16
|
411 , named_marks_(that.named_marks_)
|
Chris@16
|
412 {
|
Chris@16
|
413 if(that)
|
Chris@16
|
414 {
|
Chris@16
|
415 extras_type &extras = this->get_extras_();
|
Chris@16
|
416 std::size_t size = that.sub_matches_.size();
|
Chris@16
|
417 detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size, detail::sub_match_impl<BidiIter>(*that.base_), detail::fill);
|
Chris@16
|
418 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
|
Chris@16
|
419
|
Chris@16
|
420 this->base_ = that.base_;
|
Chris@16
|
421 this->prefix_ = that.prefix_;
|
Chris@16
|
422 this->suffix_ = that.suffix_;
|
Chris@16
|
423 // BUGBUG this doesn't share the extras::sequence_stack
|
Chris@16
|
424 this->nested_results_ = that.nested_results_;
|
Chris@16
|
425 this->traits_ = that.traits_;
|
Chris@16
|
426 }
|
Chris@16
|
427 }
|
Chris@16
|
428
|
Chris@16
|
429 ~match_results()
|
Chris@16
|
430 {
|
Chris@16
|
431 }
|
Chris@16
|
432
|
Chris@16
|
433 /// \param that The match_results object to copy.
|
Chris@16
|
434 /// \post regex_id() == that.regex_id().
|
Chris@16
|
435 /// \post size() == that.size().
|
Chris@16
|
436 /// \post empty() == that.empty().
|
Chris@16
|
437 /// \post str(n) == that.str(n) for all positive integers n \< that.size().
|
Chris@16
|
438 /// \post prefix() == that.prefix().
|
Chris@16
|
439 /// \post suffix() == that.suffix().
|
Chris@16
|
440 /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
|
Chris@16
|
441 /// \post length(n) == that.length(n) for all positive integers n \< that.size().
|
Chris@16
|
442 /// \post position(n) == that.position(n) for all positive integers n \< that.size().
|
Chris@16
|
443 match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
|
Chris@16
|
444 {
|
Chris@16
|
445 match_results<BidiIter>(that).swap(*this);
|
Chris@16
|
446 return *this;
|
Chris@16
|
447 }
|
Chris@16
|
448
|
Chris@16
|
449 /// Returns one plus the number of marked sub-expressions in the regular
|
Chris@16
|
450 /// expression that was matched if *this represents the result of a
|
Chris@16
|
451 /// successful match. Otherwise returns 0.
|
Chris@16
|
452 size_type size() const
|
Chris@16
|
453 {
|
Chris@16
|
454 return this->sub_matches_.size();
|
Chris@16
|
455 }
|
Chris@16
|
456
|
Chris@16
|
457 /// Returns size() == 0.
|
Chris@16
|
458 ///
|
Chris@16
|
459 bool empty() const
|
Chris@16
|
460 {
|
Chris@16
|
461 return 0 == this->size();
|
Chris@16
|
462 }
|
Chris@16
|
463
|
Chris@16
|
464 /// Returns (*this)[sub].length().
|
Chris@16
|
465 ///
|
Chris@16
|
466 difference_type length(size_type sub = 0) const
|
Chris@16
|
467 {
|
Chris@16
|
468 return this->sub_matches_[ sub ].length();
|
Chris@16
|
469 }
|
Chris@16
|
470
|
Chris@16
|
471 /// If !(*this)[sub].matched then returns -1. Otherwise returns std::distance(base, (*this)[sub].first),
|
Chris@16
|
472 /// where base is the start iterator of the sequence that was searched. [Note - unless this is part
|
Chris@16
|
473 /// of a repeated search with a regex_iterator then base is the same as prefix().first - end note]
|
Chris@16
|
474 difference_type position(size_type sub = 0) const
|
Chris@16
|
475 {
|
Chris@16
|
476 return this->sub_matches_[ sub ].matched ? std::distance(*this->base_, this->sub_matches_[ sub ].first) : -1;
|
Chris@16
|
477 }
|
Chris@16
|
478
|
Chris@16
|
479 /// Returns (*this)[sub].str().
|
Chris@16
|
480 ///
|
Chris@16
|
481 string_type str(size_type sub = 0) const
|
Chris@16
|
482 {
|
Chris@16
|
483 return this->sub_matches_[ sub ].str();
|
Chris@16
|
484 }
|
Chris@16
|
485
|
Chris@16
|
486 /// Returns a reference to the sub_match object representing the sequence that
|
Chris@16
|
487 /// matched marked sub-expression sub. If sub == 0 then returns a reference to
|
Chris@16
|
488 /// a sub_match object representing the sequence that matched the whole regular
|
Chris@16
|
489 /// expression. If sub >= size() then returns a sub_match object representing an
|
Chris@16
|
490 /// unmatched sub-expression.
|
Chris@16
|
491 template<typename Sub>
|
Chris@16
|
492 const_reference operator [](Sub const &sub) const
|
Chris@16
|
493 {
|
Chris@16
|
494 return this->at_(sub);
|
Chris@16
|
495 }
|
Chris@16
|
496
|
Chris@16
|
497 /// Returns a reference to the sub_match object representing the character sequence from
|
Chris@16
|
498 /// the start of the string being matched/searched, to the start of the match found.
|
Chris@16
|
499 ///
|
Chris@16
|
500 /// \pre (*this)[0].matched is true
|
Chris@16
|
501 const_reference prefix() const
|
Chris@16
|
502 {
|
Chris@16
|
503 return this->prefix_ ? *this->prefix_ : this->sub_matches_[this->sub_matches_.size()];
|
Chris@16
|
504 }
|
Chris@16
|
505
|
Chris@16
|
506 /// Returns a reference to the sub_match object representing the character sequence from
|
Chris@16
|
507 /// the end of the match found to the end of the string being matched/searched.
|
Chris@16
|
508 ///
|
Chris@16
|
509 /// \pre (*this)[0].matched is true
|
Chris@16
|
510 const_reference suffix() const
|
Chris@16
|
511 {
|
Chris@16
|
512 return this->suffix_ ? *this->suffix_ : this->sub_matches_[this->sub_matches_.size()];
|
Chris@16
|
513 }
|
Chris@16
|
514
|
Chris@16
|
515 /// Returns a starting iterator that enumerates over all the marked sub-expression matches
|
Chris@16
|
516 /// stored in *this.
|
Chris@16
|
517 ///
|
Chris@16
|
518 const_iterator begin() const
|
Chris@16
|
519 {
|
Chris@16
|
520 return this->sub_matches_.begin();
|
Chris@16
|
521 }
|
Chris@16
|
522
|
Chris@16
|
523 /// Returns a terminating iterator that enumerates over all the marked sub-expression
|
Chris@16
|
524 /// matches stored in *this.
|
Chris@16
|
525 ///
|
Chris@16
|
526 const_iterator end() const
|
Chris@16
|
527 {
|
Chris@16
|
528 return this->sub_matches_.end();
|
Chris@16
|
529 }
|
Chris@16
|
530
|
Chris@16
|
531 /// Returns a true value if (*this)[0].matched, else returns a false value.
|
Chris@16
|
532 ///
|
Chris@16
|
533 operator bool_type() const
|
Chris@16
|
534 {
|
Chris@16
|
535 return (!this->empty() && this->sub_matches_[ 0 ].matched) ? &dummy::i_ : 0;
|
Chris@16
|
536 }
|
Chris@16
|
537
|
Chris@16
|
538 /// Returns true if empty() || !(*this)[0].matched, else returns false.
|
Chris@16
|
539 ///
|
Chris@16
|
540 bool operator !() const
|
Chris@16
|
541 {
|
Chris@16
|
542 return this->empty() || !this->sub_matches_[ 0 ].matched;
|
Chris@16
|
543 }
|
Chris@16
|
544
|
Chris@16
|
545 /// Returns the id of the basic_regex object most recently used with this match_results object.
|
Chris@16
|
546 ///
|
Chris@16
|
547 regex_id_type regex_id() const
|
Chris@16
|
548 {
|
Chris@16
|
549 return this->regex_id_;
|
Chris@16
|
550 }
|
Chris@16
|
551
|
Chris@16
|
552 /// Returns a Sequence of nested match_results elements.
|
Chris@16
|
553 ///
|
Chris@16
|
554 nested_results_type const &nested_results() const
|
Chris@16
|
555 {
|
Chris@16
|
556 return this->nested_results_;
|
Chris@16
|
557 }
|
Chris@16
|
558
|
Chris@16
|
559 /// If \c Format models \c ForwardRange or is a null-terminated string, this function
|
Chris@16
|
560 /// copies the character sequence in \c fmt to \c OutputIterator \c out. For each format
|
Chris@16
|
561 /// specifier or escape sequence in \c fmt, replace that sequence with either the character(s) it
|
Chris@16
|
562 /// represents, or the sequence within <tt>*this</tt> to which it refers. The bitmasks specified in flags
|
Chris@16
|
563 /// determines what format specifiers or escape sequences are recognized. By default, this is the
|
Chris@16
|
564 /// format used by ECMA-262, ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
|
Chris@16
|
565 ///
|
Chris@16
|
566 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
|
Chris@16
|
567 /// this function returns <tt>fmt(*this, out, flags)</tt>.
|
Chris@16
|
568 ///
|
Chris@16
|
569 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
|
Chris@16
|
570 /// returns <tt>fmt(*this, out)</tt>.
|
Chris@16
|
571 ///
|
Chris@16
|
572 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
|
Chris@16
|
573 /// returns <tt>std::copy(x.begin(), x.end(), out)</tt>, where \c x is the result of
|
Chris@16
|
574 /// calling <tt>fmt(*this)</tt>.
|
Chris@16
|
575 template<typename Format, typename OutputIterator>
|
Chris@16
|
576 OutputIterator format
|
Chris@16
|
577 (
|
Chris@16
|
578 OutputIterator out
|
Chris@16
|
579 , Format const &fmt
|
Chris@16
|
580 , regex_constants::match_flag_type flags = regex_constants::format_default
|
Chris@16
|
581 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
|
Chris@16
|
582 ) const
|
Chris@16
|
583 {
|
Chris@16
|
584 // Is this a formatter object, or a format string?
|
Chris@16
|
585 typedef
|
Chris@16
|
586 typename detail::formatter_arity<
|
Chris@16
|
587 Format
|
Chris@16
|
588 , match_results<BidiIter>
|
Chris@16
|
589 , OutputIterator
|
Chris@16
|
590 >::type
|
Chris@16
|
591 arity;
|
Chris@16
|
592
|
Chris@16
|
593 return this->format_(out, fmt, flags, arity());
|
Chris@16
|
594 }
|
Chris@16
|
595
|
Chris@16
|
596 /// \overload
|
Chris@16
|
597 ///
|
Chris@16
|
598 template<typename OutputIterator>
|
Chris@16
|
599 OutputIterator format
|
Chris@16
|
600 (
|
Chris@16
|
601 OutputIterator out
|
Chris@16
|
602 , char_type const *fmt
|
Chris@16
|
603 , regex_constants::match_flag_type flags = regex_constants::format_default
|
Chris@16
|
604 ) const
|
Chris@16
|
605 {
|
Chris@16
|
606 return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
|
Chris@16
|
607 }
|
Chris@16
|
608
|
Chris@16
|
609 /// If \c Format models \c ForwardRange or is a null-terminated string, this function
|
Chris@16
|
610 /// returns a copy of the character sequence \c fmt. For each format specifier or escape sequence in \c fmt,
|
Chris@16
|
611 /// replace that sequence with either the character(s) it represents, or the sequence within
|
Chris@16
|
612 /// <tt>*this</tt> to which it refers. The bitmasks specified in \c flags determines what format specifiers
|
Chris@16
|
613 /// or escape sequences are recognized. By default this is the format used by ECMA-262,
|
Chris@16
|
614 /// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
|
Chris@16
|
615 ///
|
Chris@16
|
616 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
|
Chris@16
|
617 /// this function returns a \c string_type object \c x populated by calling <tt>fmt(*this, out, flags)</tt>,
|
Chris@16
|
618 /// where \c out is a \c back_insert_iterator into \c x.
|
Chris@16
|
619 ///
|
Chris@16
|
620 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
|
Chris@16
|
621 /// returns a \c string_type object \c x populated by calling <tt>fmt(*this, out)</tt>,
|
Chris@16
|
622 /// where \c out is a \c back_insert_iterator into \c x.
|
Chris@16
|
623 ///
|
Chris@16
|
624 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
|
Chris@16
|
625 /// returns <tt>fmt(*this)</tt>.
|
Chris@16
|
626 template<typename Format, typename OutputIterator>
|
Chris@16
|
627 string_type format
|
Chris@16
|
628 (
|
Chris@16
|
629 Format const &fmt
|
Chris@16
|
630 , regex_constants::match_flag_type flags = regex_constants::format_default
|
Chris@16
|
631 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
|
Chris@16
|
632 ) const
|
Chris@16
|
633 {
|
Chris@16
|
634 string_type result;
|
Chris@16
|
635 this->format(std::back_inserter(result), fmt, flags);
|
Chris@16
|
636 return result;
|
Chris@16
|
637 }
|
Chris@16
|
638
|
Chris@16
|
639 /// \overload
|
Chris@16
|
640 ///
|
Chris@16
|
641 string_type format
|
Chris@16
|
642 (
|
Chris@16
|
643 char_type const *fmt
|
Chris@16
|
644 , regex_constants::match_flag_type flags = regex_constants::format_default
|
Chris@16
|
645 ) const
|
Chris@16
|
646 {
|
Chris@16
|
647 string_type result;
|
Chris@16
|
648 this->format(std::back_inserter(result), fmt, flags);
|
Chris@16
|
649 return result;
|
Chris@16
|
650 }
|
Chris@16
|
651
|
Chris@16
|
652 /// Swaps the contents of two match_results objects. Guaranteed not to throw.
|
Chris@16
|
653 /// \param that The match_results object to swap with.
|
Chris@16
|
654 /// \post *this contains the sequence of matched sub-expressions that were in that,
|
Chris@16
|
655 /// that contains the sequence of matched sub-expressions that were in *this.
|
Chris@16
|
656 /// \throw nothrow
|
Chris@16
|
657 void swap(match_results<BidiIter> &that) // throw()
|
Chris@16
|
658 {
|
Chris@16
|
659 using std::swap;
|
Chris@16
|
660 swap(this->regex_id_, that.regex_id_);
|
Chris@16
|
661 this->sub_matches_.swap(that.sub_matches_);
|
Chris@16
|
662 this->base_.swap(that.base_);
|
Chris@16
|
663 this->prefix_.swap(that.prefix_);
|
Chris@16
|
664 this->suffix_.swap(that.suffix_);
|
Chris@16
|
665 this->nested_results_.swap(that.nested_results_);
|
Chris@16
|
666 this->extras_ptr_.swap(that.extras_ptr_);
|
Chris@16
|
667 this->traits_.swap(that.traits_);
|
Chris@16
|
668 this->args_.swap(that.args_);
|
Chris@16
|
669 }
|
Chris@16
|
670
|
Chris@16
|
671 /// TODO document me
|
Chris@16
|
672 ///
|
Chris@16
|
673 template<typename Arg>
|
Chris@16
|
674 match_results<BidiIter> &let(Arg const &arg)
|
Chris@16
|
675 {
|
Chris@16
|
676 typedef typename proto::result_of::left<Arg>::type left_type;
|
Chris@16
|
677 typedef typename proto::result_of::right<Arg>::type right_type;
|
Chris@16
|
678 typedef typename proto::result_of::value<left_type>::type arg_left_type;
|
Chris@16
|
679 typedef typename proto::result_of::value<right_type>::type arg_right_type;
|
Chris@16
|
680 BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
|
Chris@16
|
681 BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
|
Chris@16
|
682 this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
|
Chris@16
|
683 return *this;
|
Chris@16
|
684 }
|
Chris@16
|
685
|
Chris@16
|
686 /// INTERNAL ONLY
|
Chris@16
|
687 ///
|
Chris@16
|
688 match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
|
Chris@16
|
689 {
|
Chris@16
|
690 // BUGBUG this is linear, make it O(1)
|
Chris@16
|
691 static match_results<BidiIter> const s_null;
|
Chris@16
|
692
|
Chris@16
|
693 regex_id_filter_predicate<BidiIter> pred(regex_id);
|
Chris@16
|
694 typename nested_results_type::const_iterator
|
Chris@16
|
695 begin = this->nested_results_.begin()
|
Chris@16
|
696 , end = this->nested_results_.end()
|
Chris@16
|
697 , cur = detail::find_nth_if(begin, end, index, pred);
|
Chris@16
|
698
|
Chris@16
|
699 return (cur == end) ? s_null : *cur;
|
Chris@16
|
700 }
|
Chris@16
|
701
|
Chris@16
|
702 /// INTERNAL ONLY
|
Chris@16
|
703 ///
|
Chris@16
|
704 match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
|
Chris@16
|
705 {
|
Chris@16
|
706 return (*this)(rex.regex_id(), index);
|
Chris@16
|
707 }
|
Chris@16
|
708
|
Chris@16
|
709 private:
|
Chris@16
|
710
|
Chris@16
|
711 friend struct detail::core_access<BidiIter>;
|
Chris@16
|
712 typedef detail::results_extras<BidiIter> extras_type;
|
Chris@16
|
713
|
Chris@16
|
714 /// INTERNAL ONLY
|
Chris@16
|
715 ///
|
Chris@16
|
716 void init_
|
Chris@16
|
717 (
|
Chris@16
|
718 regex_id_type regex_id
|
Chris@16
|
719 , intrusive_ptr<detail::traits<char_type> const> const &tr
|
Chris@16
|
720 , detail::sub_match_impl<BidiIter> *sub_matches
|
Chris@16
|
721 , size_type size
|
Chris@16
|
722 , std::vector<detail::named_mark<char_type> > const &named_marks
|
Chris@16
|
723 )
|
Chris@16
|
724 {
|
Chris@16
|
725 this->traits_ = tr;
|
Chris@16
|
726 this->regex_id_ = regex_id;
|
Chris@16
|
727 this->named_marks_ = named_marks;
|
Chris@16
|
728 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
|
Chris@16
|
729 }
|
Chris@16
|
730
|
Chris@16
|
731 /// INTERNAL ONLY
|
Chris@16
|
732 ///
|
Chris@16
|
733 extras_type &get_extras_()
|
Chris@16
|
734 {
|
Chris@16
|
735 if(!this->extras_ptr_)
|
Chris@16
|
736 {
|
Chris@16
|
737 this->extras_ptr_ = new extras_type;
|
Chris@16
|
738 }
|
Chris@16
|
739
|
Chris@16
|
740 return *this->extras_ptr_;
|
Chris@16
|
741 }
|
Chris@16
|
742
|
Chris@16
|
743 /// INTERNAL ONLY
|
Chris@16
|
744 ///
|
Chris@16
|
745 void set_prefix_suffix_(BidiIter begin, BidiIter end)
|
Chris@16
|
746 {
|
Chris@16
|
747 this->base_ = begin;
|
Chris@16
|
748 this->prefix_ = sub_match<BidiIter>(begin, this->sub_matches_[ 0 ].first, begin != this->sub_matches_[ 0 ].first);
|
Chris@16
|
749 this->suffix_ = sub_match<BidiIter>(this->sub_matches_[ 0 ].second, end, this->sub_matches_[ 0 ].second != end);
|
Chris@16
|
750
|
Chris@16
|
751 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
|
Chris@16
|
752 typename nested_results_type::iterator iend = this->nested_results_.end();
|
Chris@16
|
753 for( ; ibegin != iend; ++ibegin )
|
Chris@16
|
754 {
|
Chris@16
|
755 ibegin->set_prefix_suffix_(begin, end);
|
Chris@16
|
756 }
|
Chris@16
|
757 }
|
Chris@16
|
758
|
Chris@16
|
759 /// INTERNAL ONLY
|
Chris@16
|
760 ///
|
Chris@16
|
761 void reset_()
|
Chris@16
|
762 {
|
Chris@16
|
763 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
|
Chris@16
|
764 }
|
Chris@16
|
765
|
Chris@16
|
766 /// INTERNAL ONLY
|
Chris@16
|
767 ///
|
Chris@16
|
768 void set_base_(BidiIter base)
|
Chris@16
|
769 {
|
Chris@16
|
770 this->base_ = base;
|
Chris@16
|
771
|
Chris@16
|
772 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
|
Chris@16
|
773 typename nested_results_type::iterator iend = this->nested_results_.end();
|
Chris@16
|
774 for( ; ibegin != iend; ++ibegin )
|
Chris@16
|
775 {
|
Chris@16
|
776 ibegin->set_base_(base);
|
Chris@16
|
777 }
|
Chris@16
|
778 }
|
Chris@16
|
779
|
Chris@16
|
780 /// INTERNAL ONLY
|
Chris@16
|
781 ///
|
Chris@16
|
782 const_reference at_(size_type sub) const
|
Chris@16
|
783 {
|
Chris@16
|
784 return this->sub_matches_[ sub ];
|
Chris@16
|
785 }
|
Chris@16
|
786
|
Chris@16
|
787 /// INTERNAL ONLY
|
Chris@16
|
788 ///
|
Chris@16
|
789 const_reference at_(detail::basic_mark_tag const &mark) const
|
Chris@16
|
790 {
|
Chris@16
|
791 return this->sub_matches_[ detail::get_mark_number(mark) ];
|
Chris@16
|
792 }
|
Chris@16
|
793
|
Chris@16
|
794 /// INTERNAL ONLY
|
Chris@16
|
795 ///
|
Chris@16
|
796 const_reference at_(char_type const *name) const
|
Chris@16
|
797 {
|
Chris@16
|
798 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
|
Chris@16
|
799 {
|
Chris@16
|
800 if(this->named_marks_[i].name_ == name)
|
Chris@16
|
801 {
|
Chris@16
|
802 return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
|
Chris@16
|
803 }
|
Chris@16
|
804 }
|
Chris@16
|
805 BOOST_THROW_EXCEPTION(
|
Chris@16
|
806 regex_error(regex_constants::error_badmark, "invalid named back-reference")
|
Chris@16
|
807 );
|
Chris@16
|
808 // Should never execute, but if it does, this returns
|
Chris@16
|
809 // a "null" sub_match.
|
Chris@16
|
810 return this->sub_matches_[this->sub_matches_.size()];
|
Chris@16
|
811 }
|
Chris@16
|
812
|
Chris@16
|
813 /// INTERNAL ONLY
|
Chris@16
|
814 ///
|
Chris@16
|
815 const_reference at_(string_type const &name) const
|
Chris@16
|
816 {
|
Chris@16
|
817 return (*this)[name.c_str()];
|
Chris@16
|
818 }
|
Chris@16
|
819
|
Chris@16
|
820 /// INTERNAL ONLY
|
Chris@16
|
821 ///
|
Chris@16
|
822 template<typename OutputIterator, typename ForwardRange>
|
Chris@16
|
823 OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
|
Chris@16
|
824 {
|
Chris@16
|
825 return std::copy(boost::begin(result), boost::end(result), out);
|
Chris@16
|
826 }
|
Chris@16
|
827
|
Chris@16
|
828 /// INTERNAL ONLY
|
Chris@16
|
829 ///
|
Chris@16
|
830 template<typename OutputIterator, typename Char>
|
Chris@16
|
831 OutputIterator format2_(OutputIterator out, Char const *const &result) const
|
Chris@16
|
832 {
|
Chris@16
|
833 Char const *tmp = result;
|
Chris@16
|
834 BOOST_ASSERT(0 != tmp);
|
Chris@16
|
835 for(; 0 != *tmp; ++tmp, ++out)
|
Chris@16
|
836 {
|
Chris@16
|
837 *out = *tmp;
|
Chris@16
|
838 }
|
Chris@16
|
839 return out;
|
Chris@16
|
840 }
|
Chris@16
|
841
|
Chris@16
|
842 /// INTERNAL ONLY
|
Chris@16
|
843 ///
|
Chris@16
|
844 template<typename OutputIterator, typename ForwardRange>
|
Chris@16
|
845 OutputIterator format_
|
Chris@16
|
846 (
|
Chris@16
|
847 OutputIterator out
|
Chris@16
|
848 , ForwardRange const &format
|
Chris@16
|
849 , regex_constants::match_flag_type flags
|
Chris@16
|
850 , mpl::size_t<0>
|
Chris@16
|
851 ) const
|
Chris@16
|
852 {
|
Chris@16
|
853 typedef typename range_const_iterator<ForwardRange>::type iterator;
|
Chris@16
|
854 iterator cur = boost::begin(format), end = boost::end(format);
|
Chris@16
|
855
|
Chris@16
|
856 if(0 != (regex_constants::format_literal & flags))
|
Chris@16
|
857 {
|
Chris@16
|
858 return std::copy(cur, end, out);
|
Chris@16
|
859 }
|
Chris@16
|
860 else if(0 != (regex_constants::format_perl & flags))
|
Chris@16
|
861 {
|
Chris@16
|
862 return this->format_perl_(cur, end, out);
|
Chris@16
|
863 }
|
Chris@16
|
864 else if(0 != (regex_constants::format_sed & flags))
|
Chris@16
|
865 {
|
Chris@16
|
866 return this->format_sed_(cur, end, out);
|
Chris@16
|
867 }
|
Chris@16
|
868 else if(0 != (regex_constants::format_all & flags))
|
Chris@16
|
869 {
|
Chris@16
|
870 return this->format_all_(cur, end, out);
|
Chris@16
|
871 }
|
Chris@16
|
872
|
Chris@16
|
873 return this->format_ecma_262_(cur, end, out);
|
Chris@16
|
874 }
|
Chris@16
|
875
|
Chris@16
|
876 /// INTERNAL ONLY
|
Chris@16
|
877 ///
|
Chris@16
|
878 template<typename OutputIterator, typename Callable1>
|
Chris@16
|
879 OutputIterator format_
|
Chris@16
|
880 (
|
Chris@16
|
881 OutputIterator out
|
Chris@16
|
882 , Callable1 const &format
|
Chris@16
|
883 , regex_constants::match_flag_type
|
Chris@16
|
884 , mpl::size_t<1>
|
Chris@16
|
885 ) const
|
Chris@16
|
886 {
|
Chris@16
|
887 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
|
Chris@16
|
888 return this->format2_(out, detail::as_callable(format)(*this));
|
Chris@16
|
889 #else
|
Chris@16
|
890 return this->format2_(out, format(*this));
|
Chris@16
|
891 #endif
|
Chris@16
|
892 }
|
Chris@16
|
893
|
Chris@16
|
894 /// INTERNAL ONLY
|
Chris@16
|
895 ///
|
Chris@16
|
896 template<typename OutputIterator, typename Callable2>
|
Chris@16
|
897 OutputIterator format_
|
Chris@16
|
898 (
|
Chris@16
|
899 OutputIterator out
|
Chris@16
|
900 , Callable2 const &format
|
Chris@16
|
901 , regex_constants::match_flag_type
|
Chris@16
|
902 , mpl::size_t<2>
|
Chris@16
|
903 ) const
|
Chris@16
|
904 {
|
Chris@16
|
905 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
|
Chris@16
|
906 return detail::as_callable(format)(*this, out);
|
Chris@16
|
907 #else
|
Chris@16
|
908 return format(*this, out);
|
Chris@16
|
909 #endif
|
Chris@16
|
910 }
|
Chris@16
|
911
|
Chris@16
|
912 /// INTERNAL ONLY
|
Chris@16
|
913 ///
|
Chris@16
|
914 template<typename OutputIterator, typename Callable3>
|
Chris@16
|
915 OutputIterator format_
|
Chris@16
|
916 (
|
Chris@16
|
917 OutputIterator out
|
Chris@16
|
918 , Callable3 const &format
|
Chris@16
|
919 , regex_constants::match_flag_type flags
|
Chris@16
|
920 , mpl::size_t<3>
|
Chris@16
|
921 ) const
|
Chris@16
|
922 {
|
Chris@16
|
923 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
|
Chris@16
|
924 return detail::as_callable(format)(*this, out, flags);
|
Chris@16
|
925 #else
|
Chris@16
|
926 return format(*this, out, flags);
|
Chris@16
|
927 #endif
|
Chris@16
|
928 }
|
Chris@16
|
929
|
Chris@16
|
930 /// INTERNAL ONLY
|
Chris@16
|
931 ///
|
Chris@16
|
932 template<typename OutputIterator, typename Expr>
|
Chris@16
|
933 OutputIterator format_
|
Chris@16
|
934 (
|
Chris@16
|
935 OutputIterator out
|
Chris@16
|
936 , Expr const &format
|
Chris@16
|
937 , regex_constants::match_flag_type
|
Chris@16
|
938 , mpl::size_t<4>
|
Chris@16
|
939 ) const
|
Chris@16
|
940 {
|
Chris@16
|
941 // detail::ReplaceAlgo may be an incomplete type at this point, so
|
Chris@16
|
942 // we can't construct it directly.
|
Chris@16
|
943 typedef typename mpl::if_c<true, detail::ReplaceAlgo, OutputIterator>::type ReplaceAlgo;
|
Chris@16
|
944 return this->format2_(out, ReplaceAlgo()(format, 0, *this));
|
Chris@16
|
945 }
|
Chris@16
|
946
|
Chris@16
|
947 /// INTERNAL ONLY
|
Chris@16
|
948 ///
|
Chris@16
|
949 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
950 OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
|
Chris@16
|
951 {
|
Chris@16
|
952 while(cur != end)
|
Chris@16
|
953 {
|
Chris@16
|
954 switch(*cur)
|
Chris@16
|
955 {
|
Chris@16
|
956 case BOOST_XPR_CHAR_(char_type, '$'):
|
Chris@16
|
957 out = this->format_backref_(++cur, end, out);
|
Chris@16
|
958 break;
|
Chris@16
|
959
|
Chris@16
|
960 default:
|
Chris@16
|
961 *out++ = *cur++;
|
Chris@16
|
962 break;
|
Chris@16
|
963 }
|
Chris@16
|
964 }
|
Chris@16
|
965
|
Chris@16
|
966 return out;
|
Chris@16
|
967 }
|
Chris@16
|
968
|
Chris@16
|
969 /// INTERNAL ONLY
|
Chris@16
|
970 ///
|
Chris@16
|
971 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
972 OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
|
Chris@16
|
973 {
|
Chris@16
|
974 while(cur != end)
|
Chris@16
|
975 {
|
Chris@16
|
976 switch(*cur)
|
Chris@16
|
977 {
|
Chris@16
|
978 case BOOST_XPR_CHAR_(char_type, '&'):
|
Chris@16
|
979 ++cur;
|
Chris@16
|
980 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
|
Chris@16
|
981 break;
|
Chris@16
|
982
|
Chris@16
|
983 case BOOST_XPR_CHAR_(char_type, '\\'):
|
Chris@16
|
984 out = this->format_escape_(++cur, end, out);
|
Chris@16
|
985 break;
|
Chris@16
|
986
|
Chris@16
|
987 default:
|
Chris@16
|
988 *out++ = *cur++;
|
Chris@16
|
989 break;
|
Chris@16
|
990 }
|
Chris@16
|
991 }
|
Chris@16
|
992
|
Chris@16
|
993 return out;
|
Chris@16
|
994 }
|
Chris@16
|
995
|
Chris@16
|
996 /// INTERNAL ONLY
|
Chris@16
|
997 ///
|
Chris@16
|
998 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
999 OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
|
Chris@16
|
1000 {
|
Chris@16
|
1001 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
|
Chris@16
|
1002
|
Chris@16
|
1003 while(cur != end)
|
Chris@16
|
1004 {
|
Chris@16
|
1005 switch(*cur)
|
Chris@16
|
1006 {
|
Chris@16
|
1007 case BOOST_XPR_CHAR_(char_type, '$'):
|
Chris@16
|
1008 iout = this->format_backref_(++cur, end, iout);
|
Chris@16
|
1009 break;
|
Chris@16
|
1010
|
Chris@16
|
1011 case BOOST_XPR_CHAR_(char_type, '\\'):
|
Chris@16
|
1012 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
|
Chris@16
|
1013 {
|
Chris@16
|
1014 iout = this->format_named_backref_(++cur, end, iout);
|
Chris@16
|
1015 }
|
Chris@16
|
1016 else
|
Chris@16
|
1017 {
|
Chris@16
|
1018 iout = this->format_escape_(cur, end, iout);
|
Chris@16
|
1019 }
|
Chris@16
|
1020 break;
|
Chris@16
|
1021
|
Chris@16
|
1022 default:
|
Chris@16
|
1023 *iout++ = *cur++;
|
Chris@16
|
1024 break;
|
Chris@16
|
1025 }
|
Chris@16
|
1026 }
|
Chris@16
|
1027
|
Chris@16
|
1028 return iout.base();
|
Chris@16
|
1029 }
|
Chris@16
|
1030
|
Chris@16
|
1031 /// INTERNAL ONLY
|
Chris@16
|
1032 ///
|
Chris@16
|
1033 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
1034 OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
|
Chris@16
|
1035 {
|
Chris@16
|
1036 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
|
Chris@16
|
1037 iout = this->format_all_impl_(cur, end, iout);
|
Chris@16
|
1038 BOOST_XPR_ENSURE_(cur == end
|
Chris@16
|
1039 , regex_constants::error_paren, "unbalanced parentheses in format string");
|
Chris@16
|
1040 return iout.base();
|
Chris@16
|
1041 }
|
Chris@16
|
1042
|
Chris@16
|
1043 /// INTERNAL ONLY
|
Chris@16
|
1044 ///
|
Chris@16
|
1045 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
1046 OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
|
Chris@16
|
1047 {
|
Chris@16
|
1048 int max = 0, sub = 0;
|
Chris@16
|
1049 detail::noop_output_iterator<char_type> noop;
|
Chris@16
|
1050
|
Chris@16
|
1051 while(cur != end)
|
Chris@16
|
1052 {
|
Chris@16
|
1053 switch(*cur)
|
Chris@16
|
1054 {
|
Chris@16
|
1055 case BOOST_XPR_CHAR_(char_type, '$'):
|
Chris@16
|
1056 out = this->format_backref_(++cur, end, out);
|
Chris@16
|
1057 break;
|
Chris@16
|
1058
|
Chris@16
|
1059 case BOOST_XPR_CHAR_(char_type, '\\'):
|
Chris@16
|
1060 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
|
Chris@16
|
1061 {
|
Chris@16
|
1062 out = this->format_named_backref_(++cur, end, out);
|
Chris@16
|
1063 }
|
Chris@16
|
1064 else
|
Chris@16
|
1065 {
|
Chris@16
|
1066 out = this->format_escape_(cur, end, out);
|
Chris@16
|
1067 }
|
Chris@16
|
1068 break;
|
Chris@16
|
1069
|
Chris@16
|
1070 case BOOST_XPR_CHAR_(char_type, '('):
|
Chris@16
|
1071 out = this->format_all_impl_(++cur, end, out);
|
Chris@16
|
1072 BOOST_XPR_ENSURE_(BOOST_XPR_CHAR_(char_type, ')') == *(cur-1)
|
Chris@16
|
1073 , regex_constants::error_paren, "unbalanced parentheses in format string");
|
Chris@16
|
1074 break;
|
Chris@16
|
1075
|
Chris@16
|
1076 case BOOST_XPR_CHAR_(char_type, '?'):
|
Chris@16
|
1077 BOOST_XPR_ENSURE_(++cur != end
|
Chris@16
|
1078 , regex_constants::error_subreg, "malformed conditional in format string");
|
Chris@16
|
1079 max = static_cast<int>(this->size() - 1);
|
Chris@16
|
1080 sub = detail::toi(cur, end, *this->traits_, 10, max);
|
Chris@16
|
1081 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
|
Chris@16
|
1082 if(this->sub_matches_[ sub ].matched)
|
Chris@16
|
1083 {
|
Chris@16
|
1084 out = this->format_all_impl_(cur, end, out, true);
|
Chris@16
|
1085 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
|
Chris@16
|
1086 this->format_all_impl_(cur, end, noop);
|
Chris@16
|
1087 }
|
Chris@16
|
1088 else
|
Chris@16
|
1089 {
|
Chris@16
|
1090 this->format_all_impl_(cur, end, noop, true);
|
Chris@16
|
1091 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
|
Chris@16
|
1092 out = this->format_all_impl_(cur, end, out);
|
Chris@16
|
1093 }
|
Chris@16
|
1094 return out;
|
Chris@16
|
1095
|
Chris@16
|
1096 case BOOST_XPR_CHAR_(char_type, ':'):
|
Chris@16
|
1097 if(metacolon)
|
Chris@16
|
1098 {
|
Chris@16
|
1099 BOOST_FALLTHROUGH;
|
Chris@16
|
1100 case BOOST_XPR_CHAR_(char_type, ')'):
|
Chris@16
|
1101 ++cur;
|
Chris@16
|
1102 return out;
|
Chris@16
|
1103 }
|
Chris@16
|
1104 BOOST_FALLTHROUGH;
|
Chris@16
|
1105
|
Chris@16
|
1106 default:
|
Chris@16
|
1107 *out++ = *cur++;
|
Chris@16
|
1108 break;
|
Chris@16
|
1109 }
|
Chris@16
|
1110 }
|
Chris@16
|
1111
|
Chris@16
|
1112 return out;
|
Chris@16
|
1113 }
|
Chris@16
|
1114
|
Chris@16
|
1115 /// INTERNAL ONLY
|
Chris@16
|
1116 ///
|
Chris@16
|
1117 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
1118 OutputIterator format_backref_
|
Chris@16
|
1119 (
|
Chris@16
|
1120 ForwardIterator &cur
|
Chris@16
|
1121 , ForwardIterator end
|
Chris@16
|
1122 , OutputIterator out
|
Chris@16
|
1123 ) const
|
Chris@16
|
1124 {
|
Chris@16
|
1125 if(cur == end)
|
Chris@16
|
1126 {
|
Chris@16
|
1127 *out++ = BOOST_XPR_CHAR_(char_type, '$');
|
Chris@16
|
1128 }
|
Chris@16
|
1129 else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
|
Chris@16
|
1130 {
|
Chris@16
|
1131 *out++ = *cur++;
|
Chris@16
|
1132 }
|
Chris@16
|
1133 else if(BOOST_XPR_CHAR_(char_type, '&') == *cur) // whole match
|
Chris@16
|
1134 {
|
Chris@16
|
1135 ++cur;
|
Chris@16
|
1136 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
|
Chris@16
|
1137 }
|
Chris@16
|
1138 else if(BOOST_XPR_CHAR_(char_type, '`') == *cur) // prefix
|
Chris@16
|
1139 {
|
Chris@16
|
1140 ++cur;
|
Chris@16
|
1141 out = std::copy(this->prefix().first, this->prefix().second, out);
|
Chris@16
|
1142 }
|
Chris@16
|
1143 else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur) // suffix
|
Chris@16
|
1144 {
|
Chris@16
|
1145 ++cur;
|
Chris@16
|
1146 out = std::copy(this->suffix().first, this->suffix().second, out);
|
Chris@16
|
1147 }
|
Chris@16
|
1148 else if(-1 != this->traits_->value(*cur, 10)) // a sub-match
|
Chris@16
|
1149 {
|
Chris@16
|
1150 int max = static_cast<int>(this->size() - 1);
|
Chris@16
|
1151 int sub = detail::toi(cur, end, *this->traits_, 10, max);
|
Chris@16
|
1152 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
|
Chris@16
|
1153 if(this->sub_matches_[ sub ].matched)
|
Chris@16
|
1154 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
|
Chris@16
|
1155 }
|
Chris@16
|
1156 else
|
Chris@16
|
1157 {
|
Chris@16
|
1158 *out++ = BOOST_XPR_CHAR_(char_type, '$');
|
Chris@16
|
1159 *out++ = *cur++;
|
Chris@16
|
1160 }
|
Chris@16
|
1161
|
Chris@16
|
1162 return out;
|
Chris@16
|
1163 }
|
Chris@16
|
1164
|
Chris@16
|
1165 /// INTERNAL ONLY
|
Chris@16
|
1166 ///
|
Chris@16
|
1167 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
1168 OutputIterator format_escape_
|
Chris@16
|
1169 (
|
Chris@16
|
1170 ForwardIterator &cur
|
Chris@16
|
1171 , ForwardIterator end
|
Chris@16
|
1172 , OutputIterator out
|
Chris@16
|
1173 ) const
|
Chris@16
|
1174 {
|
Chris@16
|
1175 using namespace regex_constants;
|
Chris@16
|
1176 ForwardIterator tmp;
|
Chris@16
|
1177 // define an unsigned type the same size as char_type
|
Chris@16
|
1178 typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
|
Chris@16
|
1179 BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
|
Chris@16
|
1180 typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
|
Chris@16
|
1181 numeric::converter<int, uchar_t, converstion_traits, detail::char_overflow_handler_> converter;
|
Chris@16
|
1182
|
Chris@16
|
1183 if(cur == end)
|
Chris@16
|
1184 {
|
Chris@16
|
1185 *out++ = BOOST_XPR_CHAR_(char_type, '\\');
|
Chris@16
|
1186 return out;
|
Chris@16
|
1187 }
|
Chris@16
|
1188
|
Chris@16
|
1189 char_type ch = *cur++;
|
Chris@16
|
1190 switch(ch)
|
Chris@16
|
1191 {
|
Chris@16
|
1192 case BOOST_XPR_CHAR_(char_type, 'a'):
|
Chris@16
|
1193 *out++ = BOOST_XPR_CHAR_(char_type, '\a');
|
Chris@16
|
1194 break;
|
Chris@16
|
1195
|
Chris@16
|
1196 case BOOST_XPR_CHAR_(char_type, 'e'):
|
Chris@16
|
1197 *out++ = converter(27);
|
Chris@16
|
1198 break;
|
Chris@16
|
1199
|
Chris@16
|
1200 case BOOST_XPR_CHAR_(char_type, 'f'):
|
Chris@16
|
1201 *out++ = BOOST_XPR_CHAR_(char_type, '\f');
|
Chris@16
|
1202 break;
|
Chris@16
|
1203
|
Chris@16
|
1204 case BOOST_XPR_CHAR_(char_type, 'n'):
|
Chris@16
|
1205 *out++ = BOOST_XPR_CHAR_(char_type, '\n');
|
Chris@16
|
1206 break;
|
Chris@16
|
1207
|
Chris@16
|
1208 case BOOST_XPR_CHAR_(char_type, 'r'):
|
Chris@16
|
1209 *out++ = BOOST_XPR_CHAR_(char_type, '\r');
|
Chris@16
|
1210 break;
|
Chris@16
|
1211
|
Chris@16
|
1212 case BOOST_XPR_CHAR_(char_type, 't'):
|
Chris@16
|
1213 *out++ = BOOST_XPR_CHAR_(char_type, '\t');
|
Chris@16
|
1214 break;
|
Chris@16
|
1215
|
Chris@16
|
1216 case BOOST_XPR_CHAR_(char_type, 'v'):
|
Chris@16
|
1217 *out++ = BOOST_XPR_CHAR_(char_type, '\v');
|
Chris@16
|
1218 break;
|
Chris@16
|
1219
|
Chris@16
|
1220 case BOOST_XPR_CHAR_(char_type, 'x'):
|
Chris@16
|
1221 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
|
Chris@16
|
1222 if(BOOST_XPR_CHAR_(char_type, '{') == *cur)
|
Chris@16
|
1223 {
|
Chris@16
|
1224 BOOST_XPR_ENSURE_(++cur != end, error_escape, "unexpected end of format found");
|
Chris@16
|
1225 tmp = cur;
|
Chris@16
|
1226 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xffff));
|
Chris@16
|
1227 BOOST_XPR_ENSURE_(4 == std::distance(tmp, cur) && cur != end && BOOST_XPR_CHAR_(char_type, '}') == *cur++
|
Chris@16
|
1228 , error_escape, "invalid hex escape : must be \\x { HexDigit HexDigit HexDigit HexDigit }");
|
Chris@16
|
1229 }
|
Chris@16
|
1230 else
|
Chris@16
|
1231 {
|
Chris@16
|
1232 tmp = cur;
|
Chris@16
|
1233 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xff));
|
Chris@16
|
1234 BOOST_XPR_ENSURE_(2 == std::distance(tmp, cur), error_escape
|
Chris@16
|
1235 , "invalid hex escape : must be \\x HexDigit HexDigit");
|
Chris@16
|
1236 }
|
Chris@16
|
1237 break;
|
Chris@16
|
1238
|
Chris@16
|
1239 case BOOST_XPR_CHAR_(char_type, 'c'):
|
Chris@16
|
1240 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
|
Chris@16
|
1241 BOOST_XPR_ENSURE_
|
Chris@16
|
1242 (
|
Chris@16
|
1243 this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *cur)
|
Chris@16
|
1244 || this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *cur)
|
Chris@16
|
1245 , error_escape
|
Chris@16
|
1246 , "invalid escape control letter; must be one of a-z or A-Z"
|
Chris@16
|
1247 );
|
Chris@16
|
1248 // Convert to character according to ECMA-262, section 15.10.2.10:
|
Chris@16
|
1249 *out++ = converter(*cur % 32);
|
Chris@16
|
1250 ++cur;
|
Chris@16
|
1251 break;
|
Chris@16
|
1252
|
Chris@16
|
1253 case BOOST_XPR_CHAR_(char_type, 'l'):
|
Chris@16
|
1254 if(!set_transform(out, detail::op_lower, detail::scope_next))
|
Chris@16
|
1255 {
|
Chris@16
|
1256 *out++ = BOOST_XPR_CHAR_(char_type, 'l');
|
Chris@16
|
1257 }
|
Chris@16
|
1258 break;
|
Chris@16
|
1259
|
Chris@16
|
1260 case BOOST_XPR_CHAR_(char_type, 'L'):
|
Chris@16
|
1261 if(!set_transform(out, detail::op_lower, detail::scope_rest))
|
Chris@16
|
1262 {
|
Chris@16
|
1263 *out++ = BOOST_XPR_CHAR_(char_type, 'L');
|
Chris@16
|
1264 }
|
Chris@16
|
1265 break;
|
Chris@16
|
1266
|
Chris@16
|
1267 case BOOST_XPR_CHAR_(char_type, 'u'):
|
Chris@16
|
1268 if(!set_transform(out, detail::op_upper, detail::scope_next))
|
Chris@16
|
1269 {
|
Chris@16
|
1270 *out++ = BOOST_XPR_CHAR_(char_type, 'u');
|
Chris@16
|
1271 }
|
Chris@16
|
1272 break;
|
Chris@16
|
1273
|
Chris@16
|
1274 case BOOST_XPR_CHAR_(char_type, 'U'):
|
Chris@16
|
1275 if(!set_transform(out, detail::op_upper, detail::scope_rest))
|
Chris@16
|
1276 {
|
Chris@16
|
1277 *out++ = BOOST_XPR_CHAR_(char_type, 'U');
|
Chris@16
|
1278 }
|
Chris@16
|
1279 break;
|
Chris@16
|
1280
|
Chris@16
|
1281 case BOOST_XPR_CHAR_(char_type, 'E'):
|
Chris@16
|
1282 if(!set_transform(out, detail::op_none, detail::scope_rest))
|
Chris@16
|
1283 {
|
Chris@16
|
1284 *out++ = BOOST_XPR_CHAR_(char_type, 'E');
|
Chris@16
|
1285 }
|
Chris@16
|
1286 break;
|
Chris@16
|
1287
|
Chris@16
|
1288 default:
|
Chris@16
|
1289 // BUGBUG what about backreferences like \12 ?
|
Chris@16
|
1290 if(0 < this->traits_->value(ch, 10))
|
Chris@16
|
1291 {
|
Chris@16
|
1292 int sub = this->traits_->value(ch, 10);
|
Chris@16
|
1293 if(this->sub_matches_[ sub ].matched)
|
Chris@16
|
1294 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
|
Chris@16
|
1295 }
|
Chris@16
|
1296 else
|
Chris@16
|
1297 {
|
Chris@16
|
1298 *out++ = ch;
|
Chris@16
|
1299 }
|
Chris@16
|
1300 break;
|
Chris@16
|
1301 }
|
Chris@16
|
1302
|
Chris@16
|
1303 return out;
|
Chris@16
|
1304 }
|
Chris@16
|
1305
|
Chris@16
|
1306 /// INTERNAL ONLY
|
Chris@16
|
1307 ///
|
Chris@16
|
1308 template<typename ForwardIterator, typename OutputIterator>
|
Chris@16
|
1309 OutputIterator format_named_backref_
|
Chris@16
|
1310 (
|
Chris@16
|
1311 ForwardIterator &cur
|
Chris@16
|
1312 , ForwardIterator end
|
Chris@16
|
1313 , OutputIterator out
|
Chris@16
|
1314 ) const
|
Chris@16
|
1315 {
|
Chris@16
|
1316 using namespace regex_constants;
|
Chris@16
|
1317 BOOST_XPR_ENSURE_(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
|
Chris@16
|
1318 , error_badmark, "invalid named back-reference");
|
Chris@16
|
1319 ForwardIterator begin = cur;
|
Chris@16
|
1320 for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
|
Chris@16
|
1321 {}
|
Chris@16
|
1322 BOOST_XPR_ENSURE_(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
|
Chris@16
|
1323 , error_badmark, "invalid named back-reference");
|
Chris@16
|
1324
|
Chris@16
|
1325 string_type name(begin, cur++);
|
Chris@16
|
1326 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
|
Chris@16
|
1327 {
|
Chris@16
|
1328 if(this->named_marks_[i].name_ == name)
|
Chris@16
|
1329 {
|
Chris@16
|
1330 std::size_t sub = this->named_marks_[i].mark_nbr_;
|
Chris@16
|
1331 return std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
|
Chris@16
|
1332 }
|
Chris@16
|
1333 }
|
Chris@16
|
1334
|
Chris@16
|
1335 BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
|
Chris@16
|
1336 // Should never get here
|
Chris@16
|
1337 return out;
|
Chris@16
|
1338 }
|
Chris@16
|
1339
|
Chris@16
|
1340 regex_id_type regex_id_;
|
Chris@16
|
1341 detail::sub_match_vector<BidiIter> sub_matches_;
|
Chris@16
|
1342 boost::optional<BidiIter> base_;
|
Chris@16
|
1343 boost::optional<sub_match<BidiIter> > prefix_;
|
Chris@16
|
1344 boost::optional<sub_match<BidiIter> > suffix_;
|
Chris@16
|
1345 nested_results_type nested_results_;
|
Chris@16
|
1346 intrusive_ptr<extras_type> extras_ptr_;
|
Chris@16
|
1347 intrusive_ptr<detail::traits<char_type> const> traits_;
|
Chris@16
|
1348 detail::action_args_type args_;
|
Chris@16
|
1349 std::vector<detail::named_mark<char_type> > named_marks_;
|
Chris@16
|
1350 };
|
Chris@16
|
1351
|
Chris@16
|
1352 ///////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
1353 // regex_id_filter_predicate
|
Chris@16
|
1354 //
|
Chris@16
|
1355 template<typename BidiIter>
|
Chris@16
|
1356 struct regex_id_filter_predicate
|
Chris@16
|
1357 : std::unary_function<match_results<BidiIter>, bool>
|
Chris@16
|
1358 {
|
Chris@16
|
1359 regex_id_filter_predicate(regex_id_type regex_id)
|
Chris@16
|
1360 : regex_id_(regex_id)
|
Chris@16
|
1361 {
|
Chris@16
|
1362 }
|
Chris@16
|
1363
|
Chris@16
|
1364 bool operator ()(match_results<BidiIter> const &res) const
|
Chris@16
|
1365 {
|
Chris@16
|
1366 return this->regex_id_ == res.regex_id();
|
Chris@16
|
1367 }
|
Chris@16
|
1368
|
Chris@16
|
1369 private:
|
Chris@16
|
1370
|
Chris@16
|
1371 regex_id_type regex_id_;
|
Chris@16
|
1372 };
|
Chris@16
|
1373
|
Chris@16
|
1374 }} // namespace boost::xpressive
|
Chris@16
|
1375
|
Chris@16
|
1376 #ifdef BOOST_HAS_CONCEPTS
|
Chris@16
|
1377 // Better living through concepts. :-P
|
Chris@16
|
1378 namespace std
|
Chris@16
|
1379 {
|
Chris@16
|
1380 template<typename Iter_, typename Char_>
|
Chris@16
|
1381 concept_map OutputIterator<
|
Chris@16
|
1382 boost::xpressive::detail::case_converting_iterator<Iter_, Char_>
|
Chris@16
|
1383 , Char_
|
Chris@16
|
1384 >
|
Chris@16
|
1385 {};
|
Chris@16
|
1386
|
Chris@16
|
1387 template<typename Char_>
|
Chris@16
|
1388 concept_map OutputIterator<
|
Chris@16
|
1389 boost::xpressive::detail::noop_output_iterator<Char_>
|
Chris@16
|
1390 , Char_
|
Chris@16
|
1391 >
|
Chris@16
|
1392 {};
|
Chris@16
|
1393 }
|
Chris@16
|
1394 #endif
|
Chris@16
|
1395
|
Chris@16
|
1396 #endif
|