1 /*
2  *
3  * Copyright (c) 1998-2009
4  * John Maddock
5  *
6  * Use, modification and distribution are subject to the
7  * Boost Software License, Version 1.0. (See accompanying file
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11 
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE         match_results.cpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Declares template class match_results.
17   */
18 
19 #ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP
20 #define BOOST_REGEX_V4_MATCH_RESULTS_HPP
21 
22 #ifdef BOOST_MSVC
23 #pragma warning(push)
24 #pragma warning(disable: 4103)
25 #endif
26 #ifdef BOOST_HAS_ABI_HEADERS
27 #  include BOOST_ABI_PREFIX
28 #endif
29 #ifdef BOOST_MSVC
30 #pragma warning(pop)
31 #endif
32 
33 namespace boost{
34 #ifdef BOOST_MSVC
35 #pragma warning(push)
36 #pragma warning(disable : 4251)
37 #if BOOST_MSVC < 1700
38 #     pragma warning(disable : 4231)
39 #endif
40 #  if BOOST_MSVC < 1600
41 #     pragma warning(disable : 4660)
42 #  endif
43 #endif
44 
45 namespace BOOST_REGEX_DETAIL_NS{
46 
47 class named_subexpressions;
48 
49 }
50 
51 template <class BidiIterator, class Allocator>
52 class match_results
53 {
54 private:
55 #ifndef BOOST_NO_STD_ALLOCATOR
56    typedef          std::vector<sub_match<BidiIterator>, Allocator> vector_type;
57 #else
58    typedef          std::vector<sub_match<BidiIterator> >           vector_type;
59 #endif
60 public:
61    typedef          sub_match<BidiIterator>                         value_type;
62 #ifndef BOOST_NO_CXX11_ALLOCATOR
63    typedef typename std::allocator_traits<Allocator>::value_type const &    const_reference;
64 #elif  !defined(BOOST_NO_STD_ALLOCATOR) && !(defined(BOOST_MSVC) && defined(_STLPORT_VERSION))
65    typedef typename Allocator::const_reference                              const_reference;
66 #else
67    typedef          const value_type&                                       const_reference;
68 #endif
69    typedef          const_reference                                         reference;
70    typedef typename vector_type::const_iterator                             const_iterator;
71    typedef          const_iterator                                          iterator;
72    typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits<
73                                     BidiIterator>::difference_type          difference_type;
74 #ifdef BOOST_NO_CXX11_ALLOCATOR
75    typedef typename Allocator::size_type                                    size_type;
76 #else
77    typedef typename std::allocator_traits<Allocator>::size_type             size_type;
78 #endif
79    typedef          Allocator                                               allocator_type;
80    typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits<
81                                     BidiIterator>::value_type               char_type;
82    typedef          std::basic_string<char_type>                            string_type;
83    typedef          BOOST_REGEX_DETAIL_NS::named_subexpressions                         named_sub_type;
84 
85    // construct/copy/destroy:
match_results(const Allocator & a=Allocator ())86    explicit match_results(const Allocator& a = Allocator())
87 #ifndef BOOST_NO_STD_ALLOCATOR
88       : m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {}
89 #else
90       : m_subs(), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) { (void)a; }
91 #endif
92    //
93    // IMPORTANT: in the code below, the crazy looking checks around m_is_singular are
94    // all required because it is illegal to copy a singular iterator.
95    // See https://svn.boost.org/trac/boost/ticket/3632.
96    //
match_results(const match_results & m)97    match_results(const match_results& m)
98       : m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular)
99    {
100       if(!m_is_singular)
101       {
102          m_base = m.m_base;
103          m_null = m.m_null;
104       }
105    }
operator =(const match_results & m)106    match_results& operator=(const match_results& m)
107    {
108       m_subs = m.m_subs;
109       m_named_subs = m.m_named_subs;
110       m_last_closed_paren = m.m_last_closed_paren;
111       m_is_singular = m.m_is_singular;
112       if(!m_is_singular)
113       {
114          m_base = m.m_base;
115          m_null = m.m_null;
116       }
117       return *this;
118    }
~match_results()119    ~match_results(){}
120 
121    // size:
size() const122    size_type size() const
123    { return empty() ? 0 : m_subs.size() - 2; }
max_size() const124    size_type max_size() const
125    { return m_subs.max_size(); }
empty() const126    bool empty() const
127    { return m_subs.size() < 2; }
128    // element access:
length(int sub=0) const129    difference_type length(int sub = 0) const
130    {
131       if(m_is_singular)
132          raise_logic_error();
133       sub += 2;
134       if((sub < (int)m_subs.size()) && (sub > 0))
135          return m_subs[sub].length();
136       return 0;
137    }
length(const char_type * sub) const138    difference_type length(const char_type* sub) const
139    {
140       if(m_is_singular)
141          raise_logic_error();
142       const char_type* sub_end = sub;
143       while(*sub_end) ++sub_end;
144       return length(named_subexpression_index(sub, sub_end));
145    }
146    template <class charT>
length(const charT * sub) const147    difference_type length(const charT* sub) const
148    {
149       if(m_is_singular)
150          raise_logic_error();
151       const charT* sub_end = sub;
152       while(*sub_end) ++sub_end;
153       return length(named_subexpression_index(sub, sub_end));
154    }
155    template <class charT, class Traits, class A>
length(const std::basic_string<charT,Traits,A> & sub) const156    difference_type length(const std::basic_string<charT, Traits, A>& sub) const
157    {
158       return length(sub.c_str());
159    }
position(size_type sub=0) const160    difference_type position(size_type sub = 0) const
161    {
162       if(m_is_singular)
163          raise_logic_error();
164       sub += 2;
165       if(sub < m_subs.size())
166       {
167          const sub_match<BidiIterator>& s = m_subs[sub];
168          if(s.matched || (sub == 2))
169          {
170             return ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)(m_base), (BidiIterator)(s.first));
171          }
172       }
173       return ~static_cast<difference_type>(0);
174    }
position(const char_type * sub) const175    difference_type position(const char_type* sub) const
176    {
177       const char_type* sub_end = sub;
178       while(*sub_end) ++sub_end;
179       return position(named_subexpression_index(sub, sub_end));
180    }
181    template <class charT>
position(const charT * sub) const182    difference_type position(const charT* sub) const
183    {
184       const charT* sub_end = sub;
185       while(*sub_end) ++sub_end;
186       return position(named_subexpression_index(sub, sub_end));
187    }
188    template <class charT, class Traits, class A>
position(const std::basic_string<charT,Traits,A> & sub) const189    difference_type position(const std::basic_string<charT, Traits, A>& sub) const
190    {
191       return position(sub.c_str());
192    }
str(int sub=0) const193    string_type str(int sub = 0) const
194    {
195       if(m_is_singular)
196          raise_logic_error();
197       sub += 2;
198       string_type result;
199       if(sub < (int)m_subs.size() && (sub > 0))
200       {
201          const sub_match<BidiIterator>& s = m_subs[sub];
202          if(s.matched)
203          {
204             result = s.str();
205          }
206       }
207       return result;
208    }
str(const char_type * sub) const209    string_type str(const char_type* sub) const
210    {
211       return (*this)[sub].str();
212    }
213    template <class Traits, class A>
str(const std::basic_string<char_type,Traits,A> & sub) const214    string_type str(const std::basic_string<char_type, Traits, A>& sub) const
215    {
216       return (*this)[sub].str();
217    }
218    template <class charT>
str(const charT * sub) const219    string_type str(const charT* sub) const
220    {
221       return (*this)[sub].str();
222    }
223    template <class charT, class Traits, class A>
str(const std::basic_string<charT,Traits,A> & sub) const224    string_type str(const std::basic_string<charT, Traits, A>& sub) const
225    {
226       return (*this)[sub].str();
227    }
operator [](int sub) const228    const_reference operator[](int sub) const
229    {
230       if(m_is_singular && m_subs.empty())
231          raise_logic_error();
232       sub += 2;
233       if(sub < (int)m_subs.size() && (sub >= 0))
234       {
235          return m_subs[sub];
236       }
237       return m_null;
238    }
239    //
240    // Named sub-expressions:
241    //
named_subexpression(const char_type * i,const char_type * j) const242    const_reference named_subexpression(const char_type* i, const char_type* j) const
243    {
244       //
245       // Scan for the leftmost *matched* subexpression with the specified named:
246       //
247       if(m_is_singular)
248          raise_logic_error();
249       BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j);
250       while((r.first != r.second) && ((*this)[r.first->index].matched == false))
251          ++r.first;
252       return r.first != r.second ? (*this)[r.first->index] : m_null;
253    }
254    template <class charT>
named_subexpression(const charT * i,const charT * j) const255    const_reference named_subexpression(const charT* i, const charT* j) const
256    {
257       BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type));
258       if(i == j)
259          return m_null;
260       std::vector<char_type> s;
261       while(i != j)
262          s.insert(s.end(), *i++);
263       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
264    }
named_subexpression_index(const char_type * i,const char_type * j) const265    int named_subexpression_index(const char_type* i, const char_type* j) const
266    {
267       //
268       // Scan for the leftmost *matched* subexpression with the specified named.
269       // If none found then return the leftmost expression with that name,
270       // otherwise an invalid index:
271       //
272       if(m_is_singular)
273          raise_logic_error();
274       BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r;
275       s = r = m_named_subs->equal_range(i, j);
276       while((r.first != r.second) && ((*this)[r.first->index].matched == false))
277          ++r.first;
278       if(r.first == r.second)
279          r = s;
280       return r.first != r.second ? r.first->index : -20;
281    }
282    template <class charT>
named_subexpression_index(const charT * i,const charT * j) const283    int named_subexpression_index(const charT* i, const charT* j) const
284    {
285       BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type));
286       if(i == j)
287          return -20;
288       std::vector<char_type> s;
289       while(i != j)
290          s.insert(s.end(), *i++);
291       return named_subexpression_index(&*s.begin(), &*s.begin() + s.size());
292    }
293    template <class Traits, class A>
operator [](const std::basic_string<char_type,Traits,A> & s) const294    const_reference operator[](const std::basic_string<char_type, Traits, A>& s) const
295    {
296       return named_subexpression(s.c_str(), s.c_str() + s.size());
297    }
operator [](const char_type * p) const298    const_reference operator[](const char_type* p) const
299    {
300       const char_type* e = p;
301       while(*e) ++e;
302       return named_subexpression(p, e);
303    }
304 
305    template <class charT>
operator [](const charT * p) const306    const_reference operator[](const charT* p) const
307    {
308       BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type));
309       if(*p == 0)
310          return m_null;
311       std::vector<char_type> s;
312       while(*p)
313          s.insert(s.end(), *p++);
314       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
315    }
316    template <class charT, class Traits, class A>
operator [](const std::basic_string<charT,Traits,A> & ns) const317    const_reference operator[](const std::basic_string<charT, Traits, A>& ns) const
318    {
319       BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type));
320       if(ns.empty())
321          return m_null;
322       std::vector<char_type> s;
323       for(unsigned i = 0; i < ns.size(); ++i)
324          s.insert(s.end(), ns[i]);
325       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
326    }
327 
prefix() const328    const_reference prefix() const
329    {
330       if(m_is_singular)
331          raise_logic_error();
332       return (*this)[-1];
333    }
334 
suffix() const335    const_reference suffix() const
336    {
337       if(m_is_singular)
338          raise_logic_error();
339       return (*this)[-2];
340    }
begin() const341    const_iterator begin() const
342    {
343       return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end();
344    }
end() const345    const_iterator end() const
346    {
347       return m_subs.end();
348    }
349    // format:
350    template <class OutputIterator, class Functor>
351    OutputIterator format(OutputIterator out,
352                          Functor fmt,
353                          match_flag_type flags = format_default) const
354    {
355       if(m_is_singular)
356          raise_logic_error();
357       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator>::type F;
358       F func(fmt);
359       return func(*this, out, flags);
360    }
361    template <class Functor>
format(Functor fmt,match_flag_type flags=format_default) const362    string_type format(Functor fmt, match_flag_type flags = format_default) const
363    {
364       if(m_is_singular)
365          raise_logic_error();
366       std::basic_string<char_type> result;
367       BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
368 
369       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > >::type F;
370       F func(fmt);
371 
372       func(*this, i, flags);
373       return result;
374    }
375    // format with locale:
376    template <class OutputIterator, class Functor, class RegexT>
377    OutputIterator format(OutputIterator out,
378                          Functor fmt,
379                          match_flag_type flags,
380                          const RegexT& re) const
381    {
382       if(m_is_singular)
383          raise_logic_error();
384       typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
385       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator, traits_type>::type F;
386       F func(fmt);
387       return func(*this, out, flags, re.get_traits());
388    }
389    template <class RegexT, class Functor>
format(Functor fmt,match_flag_type flags,const RegexT & re) const390    string_type format(Functor fmt,
391                       match_flag_type flags,
392                       const RegexT& re) const
393    {
394       if(m_is_singular)
395          raise_logic_error();
396       typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
397       std::basic_string<char_type> result;
398       BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
399 
400       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> >, traits_type >::type F;
401       F func(fmt);
402 
403       func(*this, i, flags, re.get_traits());
404       return result;
405    }
406 
get_last_closed_paren() const407    const_reference get_last_closed_paren()const
408    {
409       if(m_is_singular)
410          raise_logic_error();
411       return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
412    }
413 
get_allocator() const414    allocator_type get_allocator() const
415    {
416 #ifndef BOOST_NO_STD_ALLOCATOR
417       return m_subs.get_allocator();
418 #else
419      return allocator_type();
420 #endif
421    }
swap(match_results & that)422    void swap(match_results& that)
423    {
424       std::swap(m_subs, that.m_subs);
425       std::swap(m_named_subs, that.m_named_subs);
426       std::swap(m_last_closed_paren, that.m_last_closed_paren);
427       if(m_is_singular)
428       {
429          if(!that.m_is_singular)
430          {
431             m_base = that.m_base;
432             m_null = that.m_null;
433          }
434       }
435       else if(that.m_is_singular)
436       {
437          that.m_base = m_base;
438          that.m_null = m_null;
439       }
440       else
441       {
442          std::swap(m_base, that.m_base);
443          std::swap(m_null, that.m_null);
444       }
445       std::swap(m_is_singular, that.m_is_singular);
446    }
operator ==(const match_results & that) const447    bool operator==(const match_results& that)const
448    {
449       if(m_is_singular)
450       {
451          return that.m_is_singular;
452       }
453       else if(that.m_is_singular)
454       {
455          return false;
456       }
457       return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren);
458    }
operator !=(const match_results & that) const459    bool operator!=(const match_results& that)const
460    { return !(*this == that); }
461 
462 #ifdef BOOST_REGEX_MATCH_EXTRA
463    typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type;
464 
captures(int i) const465    const capture_sequence_type& captures(int i)const
466    {
467       if(m_is_singular)
468          raise_logic_error();
469       return (*this)[i].captures();
470    }
471 #endif
472 
473    //
474    // private access functions:
set_second(BidiIterator i)475    void BOOST_REGEX_CALL set_second(BidiIterator i)
476    {
477       BOOST_ASSERT(m_subs.size() > 2);
478       m_subs[2].second = i;
479       m_subs[2].matched = true;
480       m_subs[0].first = i;
481       m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
482       m_null.first = i;
483       m_null.second = i;
484       m_null.matched = false;
485       m_is_singular = false;
486    }
487 
set_second(BidiIterator i,size_type pos,bool m=true,bool escape_k=false)488    void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
489    {
490       if(pos)
491          m_last_closed_paren = static_cast<int>(pos);
492       pos += 2;
493       BOOST_ASSERT(m_subs.size() > pos);
494       m_subs[pos].second = i;
495       m_subs[pos].matched = m;
496       if((pos == 2) && !escape_k)
497       {
498          m_subs[0].first = i;
499          m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
500          m_null.first = i;
501          m_null.second = i;
502          m_null.matched = false;
503          m_is_singular = false;
504       }
505    }
set_size(size_type n,BidiIterator i,BidiIterator j)506    void BOOST_REGEX_CALL set_size(size_type n, BidiIterator i, BidiIterator j)
507    {
508       value_type v(j);
509       size_type len = m_subs.size();
510       if(len > n + 2)
511       {
512          m_subs.erase(m_subs.begin()+n+2, m_subs.end());
513          std::fill(m_subs.begin(), m_subs.end(), v);
514       }
515       else
516       {
517          std::fill(m_subs.begin(), m_subs.end(), v);
518          if(n+2 != len)
519             m_subs.insert(m_subs.end(), n+2-len, v);
520       }
521       m_subs[1].first = i;
522       m_last_closed_paren = 0;
523    }
set_base(BidiIterator pos)524    void BOOST_REGEX_CALL set_base(BidiIterator pos)
525    {
526       m_base = pos;
527    }
base() const528    BidiIterator base()const
529    {
530       return m_base;
531    }
set_first(BidiIterator i)532    void BOOST_REGEX_CALL set_first(BidiIterator i)
533    {
534       BOOST_ASSERT(m_subs.size() > 2);
535       // set up prefix:
536       m_subs[1].second = i;
537       m_subs[1].matched = (m_subs[1].first != i);
538       // set up $0:
539       m_subs[2].first = i;
540       // zero out everything else:
541       for(size_type n = 3; n < m_subs.size(); ++n)
542       {
543          m_subs[n].first = m_subs[n].second = m_subs[0].second;
544          m_subs[n].matched = false;
545       }
546    }
set_first(BidiIterator i,size_type pos,bool escape_k=false)547    void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos, bool escape_k = false)
548    {
549       BOOST_ASSERT(pos+2 < m_subs.size());
550       if(pos || escape_k)
551       {
552          m_subs[pos+2].first = i;
553          if(escape_k)
554          {
555             m_subs[1].second = i;
556             m_subs[1].matched = (m_subs[1].first != m_subs[1].second);
557          }
558       }
559       else
560          set_first(i);
561    }
562    void BOOST_REGEX_CALL maybe_assign(const match_results<BidiIterator, Allocator>& m);
563 
set_named_subs(boost::shared_ptr<named_sub_type> subs)564    void BOOST_REGEX_CALL set_named_subs(boost::shared_ptr<named_sub_type> subs)
565    {
566       m_named_subs = subs;
567    }
568 
569 private:
570    //
571    // Error handler called when an uninitialized match_results is accessed:
572    //
raise_logic_error()573    static void raise_logic_error()
574    {
575       std::logic_error e("Attempt to access an uninitialized boost::match_results<> class.");
576       boost::throw_exception(e);
577    }
578 
579 
580    vector_type            m_subs;                      // subexpressions
581    BidiIterator   m_base;                              // where the search started from
582    sub_match<BidiIterator> m_null;                     // a null match
583    boost::shared_ptr<named_sub_type> m_named_subs;     // Shared copy of named subs in the regex object
584    int m_last_closed_paren;                            // Last ) to be seen - used for formatting
585    bool m_is_singular;                                 // True if our stored iterators are singular
586 };
587 
588 template <class BidiIterator, class Allocator>
maybe_assign(const match_results<BidiIterator,Allocator> & m)589 void BOOST_REGEX_CALL match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
590 {
591    if(m_is_singular)
592    {
593       *this = m;
594       return;
595    }
596    const_iterator p1, p2;
597    p1 = begin();
598    p2 = m.begin();
599    //
600    // Distances are measured from the start of *this* match, unless this isn't
601    // a valid match in which case we use the start of the whole sequence.  Note that
602    // no subsequent match-candidate can ever be to the left of the first match found.
603    // This ensures that when we are using bidirectional iterators, that distances
604    // measured are as short as possible, and therefore as efficient as possible
605    // to compute.  Finally note that we don't use the "matched" data member to test
606    // whether a sub-expression is a valid match, because partial matches set this
607    // to false for sub-expression 0.
608    //
609    BidiIterator l_end = this->suffix().second;
610    BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first;
611    difference_type len1 = 0;
612    difference_type len2 = 0;
613    difference_type base1 = 0;
614    difference_type base2 = 0;
615    std::size_t i;
616    for(i = 0; i < size(); ++i, ++p1, ++p2)
617    {
618       //
619       // Leftmost takes priority over longest; handle special cases
620       // where distances need not be computed first (an optimisation
621       // for bidirectional iterators: ensure that we don't accidently
622       // compute the length of the whole sequence, as this can be really
623       // expensive).
624       //
625       if(p1->first == l_end)
626       {
627          if(p2->first != l_end)
628          {
629             // p2 must be better than p1, and no need to calculate
630             // actual distances:
631             base1 = 1;
632             base2 = 0;
633             break;
634          }
635          else
636          {
637             // *p1 and *p2 are either unmatched or match end-of sequence,
638             // either way no need to calculate distances:
639             if((p1->matched == false) && (p2->matched == true))
640                break;
641             if((p1->matched == true) && (p2->matched == false))
642                return;
643             continue;
644          }
645       }
646       else if(p2->first == l_end)
647       {
648          // p1 better than p2, and no need to calculate distances:
649          return;
650       }
651       base1 = ::boost::BOOST_REGEX_DETAIL_NS::distance(l_base, p1->first);
652       base2 = ::boost::BOOST_REGEX_DETAIL_NS::distance(l_base, p2->first);
653       BOOST_ASSERT(base1 >= 0);
654       BOOST_ASSERT(base2 >= 0);
655       if(base1 < base2) return;
656       if(base2 < base1) break;
657 
658       len1 = ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
659       len2 = ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
660       BOOST_ASSERT(len1 >= 0);
661       BOOST_ASSERT(len2 >= 0);
662       if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
663          break;
664       if((p1->matched == true) && (p2->matched == false))
665          return;
666    }
667    if(i == size())
668       return;
669    if(base2 < base1)
670       *this = m;
671    else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
672       *this = m;
673 }
674 
675 template <class BidiIterator, class Allocator>
swap(match_results<BidiIterator,Allocator> & a,match_results<BidiIterator,Allocator> & b)676 void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b)
677 {
678    a.swap(b);
679 }
680 
681 #ifndef BOOST_NO_STD_LOCALE
682 template <class charT, class traits, class BidiIterator, class Allocator>
683 std::basic_ostream<charT, traits>&
operator <<(std::basic_ostream<charT,traits> & os,const match_results<BidiIterator,Allocator> & s)684    operator << (std::basic_ostream<charT, traits>& os,
685                 const match_results<BidiIterator, Allocator>& s)
686 {
687    return (os << s.str());
688 }
689 #else
690 template <class BidiIterator, class Allocator>
operator <<(std::ostream & os,const match_results<BidiIterator,Allocator> & s)691 std::ostream& operator << (std::ostream& os,
692                            const match_results<BidiIterator, Allocator>& s)
693 {
694    return (os << s.str());
695 }
696 #endif
697 
698 #ifdef BOOST_MSVC
699 #pragma warning(pop)
700 #endif
701 } // namespace boost
702 
703 #ifdef BOOST_MSVC
704 #pragma warning(push)
705 #pragma warning(disable: 4103)
706 #endif
707 #ifdef BOOST_HAS_ABI_HEADERS
708 #  include BOOST_ABI_SUFFIX
709 #endif
710 #ifdef BOOST_MSVC
711 #pragma warning(pop)
712 #endif
713 
714 #endif
715 
716 
717