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