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 {
operator ()boost::xpressive::detail::type_info_less75     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 {
operator ()boost::xpressive::detail::char_overflow_handler_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 {
case_converting_iteratorboost::xpressive::detail::case_converting_iterator132     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 
baseboost::xpressive::detail::case_converting_iterator139     OutputIterator base() const
140     {
141         return this->out_;
142     }
143 
operator ++boost::xpressive::detail::case_converting_iterator144     case_converting_iterator &operator ++()
145     {
146         ++this->out_;
147         this->next_ = op_none;
148         return *this;
149     }
150 
operator ++boost::xpressive::detail::case_converting_iterator151     case_converting_iterator operator ++(int)
152     {
153         case_converting_iterator tmp(*this);
154         ++*this;
155         return tmp;
156     }
157 
operator *boost::xpressive::detail::case_converting_iterator158     case_converting_iterator &operator *()
159     {
160         return *this;
161     }
162 
set_transform(case_converting_iterator & iter,transform_op trans,transform_scope scope)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 
operator =boost::xpressive::detail::case_converting_iterator173     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>
set_transform(Iterator &,transform_op,transform_scope)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 {
operator ++boost::xpressive::detail::noop_output_iterator211     noop_output_iterator &operator ++()
212     {
213         return *this;
214     }
215 
operator ++boost::xpressive::detail::noop_output_iterator216     noop_output_iterator &operator ++(int)
217     {
218         return *this;
219     }
220 
operator *boost::xpressive::detail::noop_output_iterator221     noop_output_iterator &operator *()
222     {
223         return *this;
224     }
225 
operator =boost::xpressive::detail::noop_output_iterator226     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
as_callable(T const & t)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()
match_resultsboost::xpressive::match_results377     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().
match_resultsboost::xpressive::match_results401     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 
~match_resultsboost::xpressive::match_results429     ~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().
operator =boost::xpressive::match_results443     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.
sizeboost::xpressive::match_results452     size_type size() const
453     {
454         return this->sub_matches_.size();
455     }
456 
457     /// Returns size() == 0.
458     ///
emptyboost::xpressive::match_results459     bool empty() const
460     {
461         return 0 == this->size();
462     }
463 
464     /// Returns (*this)[sub].length().
465     ///
lengthboost::xpressive::match_results466     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]
positionboost::xpressive::match_results474     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     ///
strboost::xpressive::match_results481     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>
operator []boost::xpressive::match_results492     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
prefixboost::xpressive::match_results501     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
suffixboost::xpressive::match_results510     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     ///
beginboost::xpressive::match_results518     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     ///
endboost::xpressive::match_results526     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     ///
operator bool_typeboost::xpressive::match_results533     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     ///
operator !boost::xpressive::match_results540     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     ///
regex_idboost::xpressive::match_results547     regex_id_type regex_id() const
548     {
549         return this->regex_id_;
550     }
551 
552     /// Returns a Sequence of nested match_results elements.
553     ///
nested_resultsboost::xpressive::match_results554     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>
formatboost::xpressive::match_results576     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>
formatboost::xpressive::match_results599     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>
formatboost::xpressive::match_results627     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     ///
formatboost::xpressive::match_results641     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
swapboost::xpressive::match_results657     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>
letboost::xpressive::match_results674     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     ///
operator ()boost::xpressive::match_results688     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     ///
operator ()boost::xpressive::match_results704     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     ///
init_boost::xpressive::match_results716     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     ///
get_extras_boost::xpressive::match_results733     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     ///
set_prefix_suffix_boost::xpressive::match_results745     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     ///
reset_boost::xpressive::match_results761     void reset_()
762     {
763         detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
764     }
765 
766     /// INTERNAL ONLY
767     ///
set_base_boost::xpressive::match_results768     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     ///
at_boost::xpressive::match_results782     const_reference at_(size_type sub) const
783     {
784         return this->sub_matches_[ sub ];
785     }
786 
787     /// INTERNAL ONLY
788     ///
at_boost::xpressive::match_results789     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     ///
at_boost::xpressive::match_results796     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     ///
at_boost::xpressive::match_results815     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>
format_ecma_262_boost::xpressive::match_results950     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>
format_sed_boost::xpressive::match_results972     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>
format_perl_boost::xpressive::match_results999     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>
format_all_boost::xpressive::match_results1034     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>
format_all_impl_boost::xpressive::match_results1046     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>
format_backref_boost::xpressive::match_results1118     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>
format_escape_boost::xpressive::match_results1168     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>
format_named_backref_boost::xpressive::match_results1309     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 {
regex_id_filter_predicateboost::xpressive::regex_id_filter_predicate1359     regex_id_filter_predicate(regex_id_type regex_id)
1360       : regex_id_(regex_id)
1361     {
1362     }
1363 
operator ()boost::xpressive::regex_id_filter_predicate1364     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
1397