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