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