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