Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-16 09:32:55

0001 /*
0002  *
0003  * Copyright (c) 1998-2009
0004  * John Maddock
0005  *
0006  * Use, modification and distribution are subject to the 
0007  * Boost Software License, Version 1.0. (See accompanying file 
0008  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009  *
0010  */
0011 
0012  /*
0013   *   LOCATION:    see http://www.boost.org for most recent version.
0014   *   FILE         match_results.cpp
0015   *   VERSION      see <boost/version.hpp>
0016   *   DESCRIPTION: Declares template class match_results.
0017   */
0018 
0019 #ifndef BOOST_REGEX_V5_MATCH_RESULTS_HPP
0020 #define BOOST_REGEX_V5_MATCH_RESULTS_HPP
0021 
0022 namespace boost{
0023 #ifdef BOOST_REGEX_MSVC
0024 #pragma warning(push)
0025 #pragma warning(disable : 4251 4459)
0026 #if BOOST_REGEX_MSVC < 1700
0027 #     pragma warning(disable : 4231)
0028 #endif
0029 #  if BOOST_REGEX_MSVC < 1600
0030 #     pragma warning(disable : 4660)
0031 #  endif
0032 #endif
0033 
0034 namespace BOOST_REGEX_DETAIL_NS{
0035 
0036 class named_subexpressions;
0037 
0038 }
0039 
0040 template <class BidiIterator, class Allocator>
0041 class match_results
0042 { 
0043 private:
0044    typedef          std::vector<sub_match<BidiIterator>, Allocator> vector_type;
0045 public: 
0046    typedef          sub_match<BidiIterator>                         value_type;
0047    typedef typename std::allocator_traits<Allocator>::value_type const &    const_reference;
0048    typedef          const_reference                                         reference;
0049    typedef typename vector_type::const_iterator                             const_iterator;
0050    typedef          const_iterator                                          iterator;
0051    typedef typename std::iterator_traits<
0052                                     BidiIterator>::difference_type          difference_type;
0053    typedef typename std::allocator_traits<Allocator>::size_type             size_type;
0054    typedef          Allocator                                               allocator_type;
0055    typedef typename std::iterator_traits<
0056                                     BidiIterator>::value_type               char_type;
0057    typedef          std::basic_string<char_type>                            string_type;
0058    typedef          BOOST_REGEX_DETAIL_NS::named_subexpressions             named_sub_type;
0059 
0060    // construct/copy/destroy:
0061    explicit match_results(const Allocator& a = Allocator())
0062       : m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {}
0063    //
0064    // IMPORTANT: in the code below, the crazy looking checks around m_is_singular are
0065    // all required because it is illegal to copy a singular iterator.
0066    // See https://svn.boost.org/trac/boost/ticket/3632.
0067    //
0068    match_results(const match_results& m)
0069       : 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)
0070    {
0071       if(!m_is_singular)
0072       {
0073          m_base = m.m_base;
0074          m_null = m.m_null;
0075       }
0076    }
0077    match_results& operator=(const match_results& m)
0078    {
0079       m_subs = m.m_subs;
0080       m_named_subs = m.m_named_subs;
0081       m_last_closed_paren = m.m_last_closed_paren;
0082       m_is_singular = m.m_is_singular;
0083       if(!m_is_singular)
0084       {
0085          m_base = m.m_base;
0086          m_null = m.m_null;
0087       }
0088       return *this;
0089    }
0090    ~match_results(){}
0091 
0092    // size:
0093    size_type size() const
0094    { return empty() ? 0 : m_subs.size() - 2; }
0095    size_type max_size() const
0096    { return m_subs.max_size(); }
0097    bool empty() const
0098    { return m_subs.size() < 2; }
0099    // element access:
0100    difference_type length(int sub = 0) const
0101    {
0102       if(m_is_singular)
0103          raise_logic_error();
0104       sub += 2;
0105       if((sub < (int)m_subs.size()) && (sub > 0))
0106          return m_subs[sub].length();
0107       return 0;
0108    }
0109    difference_type length(const char_type* sub) const
0110    {
0111       if(m_is_singular)
0112          raise_logic_error();
0113       const char_type* sub_end = sub;
0114       while(*sub_end) ++sub_end;
0115       return length(named_subexpression_index(sub, sub_end));
0116    }
0117    template <class charT>
0118    difference_type length(const charT* sub) const
0119    {
0120       if(m_is_singular)
0121          raise_logic_error();
0122       const charT* sub_end = sub;
0123       while(*sub_end) ++sub_end;
0124       return length(named_subexpression_index(sub, sub_end));
0125    }
0126    template <class charT, class Traits, class A>
0127    difference_type length(const std::basic_string<charT, Traits, A>& sub) const
0128    {
0129       return length(sub.c_str());
0130    }
0131    difference_type position(size_type sub = 0) const
0132    {
0133       if(m_is_singular)
0134          raise_logic_error();
0135       sub += 2;
0136       if(sub < m_subs.size())
0137       {
0138          const sub_match<BidiIterator>& s = m_subs[sub];
0139          if(s.matched || (sub == 2))
0140          {
0141             return std::distance((BidiIterator)(m_base), (BidiIterator)(s.first));
0142          }
0143       }
0144       return ~static_cast<difference_type>(0);
0145    }
0146    difference_type position(const char_type* sub) const
0147    {
0148       const char_type* sub_end = sub;
0149       while(*sub_end) ++sub_end;
0150       return position(named_subexpression_index(sub, sub_end));
0151    }
0152    template <class charT>
0153    difference_type position(const charT* sub) const
0154    {
0155       const charT* sub_end = sub;
0156       while(*sub_end) ++sub_end;
0157       return position(named_subexpression_index(sub, sub_end));
0158    }
0159    template <class charT, class Traits, class A>
0160    difference_type position(const std::basic_string<charT, Traits, A>& sub) const
0161    {
0162       return position(sub.c_str());
0163    }
0164    string_type str(int sub = 0) const
0165    {
0166       if(m_is_singular)
0167          raise_logic_error();
0168       sub += 2;
0169       string_type result;
0170       if(sub < (int)m_subs.size() && (sub > 0))
0171       {
0172          const sub_match<BidiIterator>& s = m_subs[sub];
0173          if(s.matched)
0174          {
0175             result = s.str();
0176          }
0177       }
0178       return result;
0179    }
0180    string_type str(const char_type* sub) const
0181    {
0182       return (*this)[sub].str();
0183    }
0184    template <class Traits, class A>
0185    string_type str(const std::basic_string<char_type, Traits, A>& sub) const
0186    {
0187       return (*this)[sub].str();
0188    }
0189    template <class charT>
0190    string_type str(const charT* sub) const
0191    {
0192       return (*this)[sub].str();
0193    }
0194    template <class charT, class Traits, class A>
0195    string_type str(const std::basic_string<charT, Traits, A>& sub) const
0196    {
0197       return (*this)[sub].str();
0198    }
0199    const_reference operator[](int sub) const
0200    {
0201       if(m_is_singular && m_subs.empty())
0202          raise_logic_error();
0203       sub += 2;
0204       if(sub < (int)m_subs.size() && (sub >= 0))
0205       {
0206          return m_subs[sub];
0207       }
0208       return m_null;
0209    }
0210    //
0211    // Named sub-expressions:
0212    //
0213    const_reference named_subexpression(const char_type* i, const char_type* j) const
0214    {
0215       //
0216       // Scan for the leftmost *matched* subexpression with the specified named:
0217       //
0218       if(m_is_singular)
0219          raise_logic_error();
0220       BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j);
0221       while((r.first != r.second) && ((*this)[r.first->index].matched == false))
0222          ++r.first;
0223       return r.first != r.second ? (*this)[r.first->index] : m_null;
0224    }
0225    template <class charT>
0226    const_reference named_subexpression(const charT* i, const charT* j) const
0227    {
0228       static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
0229       if(i == j)
0230          return m_null;
0231       std::vector<char_type> s;
0232       while(i != j)
0233          s.insert(s.end(), *i++);
0234       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
0235    }
0236    int named_subexpression_index(const char_type* i, const char_type* j) const
0237    {
0238       //
0239       // Scan for the leftmost *matched* subexpression with the specified named.
0240       // If none found then return the leftmost expression with that name,
0241       // otherwise an invalid index:
0242       //
0243       if(m_is_singular)
0244          raise_logic_error();
0245       BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r;
0246       s = r = m_named_subs->equal_range(i, j);
0247       while((r.first != r.second) && ((*this)[r.first->index].matched == false))
0248          ++r.first;
0249       if(r.first == r.second)
0250          r = s;
0251       return r.first != r.second ? r.first->index : -20;
0252    }
0253    template <class charT>
0254    int named_subexpression_index(const charT* i, const charT* j) const
0255    {
0256       static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
0257       if(i == j)
0258          return -20;
0259       std::vector<char_type> s;
0260       while(i != j)
0261          s.insert(s.end(), *i++);
0262       return named_subexpression_index(&*s.begin(), &*s.begin() + s.size());
0263    }
0264    template <class Traits, class A>
0265    const_reference operator[](const std::basic_string<char_type, Traits, A>& s) const
0266    {
0267       return named_subexpression(s.c_str(), s.c_str() + s.size());
0268    }
0269    const_reference operator[](const char_type* p) const
0270    {
0271       const char_type* e = p;
0272       while(*e) ++e;
0273       return named_subexpression(p, e);
0274    }
0275 
0276    template <class charT>
0277    const_reference operator[](const charT* p) const
0278    {
0279       static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
0280       if(*p == 0)
0281          return m_null;
0282       std::vector<char_type> s;
0283       while(*p)
0284          s.insert(s.end(), *p++);
0285       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
0286    }
0287    template <class charT, class Traits, class A>
0288    const_reference operator[](const std::basic_string<charT, Traits, A>& ns) const
0289    {
0290       static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
0291       if(ns.empty())
0292          return m_null;
0293       std::vector<char_type> s;
0294       for(unsigned i = 0; i < ns.size(); ++i)
0295          s.insert(s.end(), ns[i]);
0296       return named_subexpression(&*s.begin(), &*s.begin() + s.size());
0297    }
0298 
0299    const_reference prefix() const
0300    {
0301       if(m_is_singular)
0302          raise_logic_error();
0303       return (*this)[-1];
0304    }
0305 
0306    const_reference suffix() const
0307    {
0308       if(m_is_singular)
0309          raise_logic_error();
0310       return (*this)[-2];
0311    }
0312    const_iterator begin() const
0313    {
0314       return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end();
0315    }
0316    const_iterator end() const
0317    {
0318       return m_subs.end();
0319    }
0320    // format:
0321    template <class OutputIterator, class Functor>
0322    OutputIterator format(OutputIterator out,
0323                          Functor fmt,
0324                          match_flag_type flags = format_default) const
0325    {
0326       if(m_is_singular)
0327          raise_logic_error();
0328       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator>::type F;
0329       F func(fmt);
0330       return func(*this, out, flags);
0331    }
0332    template <class Functor>
0333    string_type format(Functor fmt, match_flag_type flags = format_default) const
0334    {
0335       if(m_is_singular)
0336          raise_logic_error();
0337       std::basic_string<char_type> result;
0338       BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
0339 
0340       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;
0341       F func(fmt);
0342 
0343       func(*this, i, flags);
0344       return result;
0345    }
0346    // format with locale:
0347    template <class OutputIterator, class Functor, class RegexT>
0348    OutputIterator format(OutputIterator out,
0349                          Functor fmt,
0350                          match_flag_type flags,
0351                          const RegexT& re) const
0352    {
0353       if(m_is_singular)
0354          raise_logic_error();
0355       typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
0356       typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator, traits_type>::type F;
0357       F func(fmt);
0358       return func(*this, out, flags, re.get_traits());
0359    }
0360    template <class RegexT, class Functor>
0361    string_type format(Functor fmt,
0362                       match_flag_type flags,
0363                       const RegexT& re) const
0364    {
0365       if(m_is_singular)
0366          raise_logic_error();
0367       typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
0368       std::basic_string<char_type> result;
0369       BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
0370 
0371       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;
0372       F func(fmt);
0373 
0374       func(*this, i, flags, re.get_traits());
0375       return result;
0376    }
0377 
0378    const_reference get_last_closed_paren()const
0379    {
0380       if(m_is_singular)
0381          raise_logic_error();
0382       return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
0383    }
0384 
0385    allocator_type get_allocator() const
0386    {
0387       return m_subs.get_allocator();
0388    }
0389    void swap(match_results& that)
0390    {
0391       std::swap(m_subs, that.m_subs);
0392       std::swap(m_named_subs, that.m_named_subs);
0393       std::swap(m_last_closed_paren, that.m_last_closed_paren);
0394       if(m_is_singular)
0395       {
0396          if(!that.m_is_singular)
0397          {
0398             m_base = that.m_base;
0399             m_null = that.m_null;
0400          }
0401       }
0402       else if(that.m_is_singular)
0403       {
0404          that.m_base = m_base;
0405          that.m_null = m_null;
0406       }
0407       else
0408       {
0409          std::swap(m_base, that.m_base);
0410          std::swap(m_null, that.m_null);
0411       }
0412       std::swap(m_is_singular, that.m_is_singular);
0413    }
0414    bool operator==(const match_results& that)const
0415    {
0416       if(m_is_singular)
0417       {
0418          return that.m_is_singular;
0419       }
0420       else if(that.m_is_singular)
0421       {
0422          return false;
0423       }
0424       return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren);
0425    }
0426    bool operator!=(const match_results& that)const
0427    { return !(*this == that); }
0428 
0429 #ifdef BOOST_REGEX_MATCH_EXTRA
0430    typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type;
0431 
0432    const capture_sequence_type& captures(int i)const
0433    {
0434       if(m_is_singular)
0435          raise_logic_error();
0436       return (*this)[i].captures();
0437    }
0438 #endif
0439 
0440    //
0441    // private access functions:
0442    void  set_second(BidiIterator i)
0443    {
0444       BOOST_REGEX_ASSERT(m_subs.size() > 2);
0445       m_subs[2].second = i;
0446       m_subs[2].matched = true;
0447       m_subs[0].first = i;
0448       m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
0449       m_null.first = i;
0450       m_null.second = i;
0451       m_null.matched = false;
0452       m_is_singular = false;
0453    }
0454 
0455    void  set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
0456    {
0457       if(pos)
0458          m_last_closed_paren = static_cast<int>(pos);
0459       pos += 2;
0460       BOOST_REGEX_ASSERT(m_subs.size() > pos);
0461       m_subs[pos].second = i;
0462       m_subs[pos].matched = m;
0463       if((pos == 2) && !escape_k)
0464       {
0465          m_subs[0].first = i;
0466          m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
0467          m_null.first = i;
0468          m_null.second = i;
0469          m_null.matched = false;
0470          m_is_singular = false;
0471       }
0472    }
0473    void  set_size(size_type n, BidiIterator i, BidiIterator j)
0474    {
0475       value_type v(j);
0476       size_type len = m_subs.size();
0477       if(len > n + 2)
0478       {
0479          m_subs.erase(m_subs.begin()+n+2, m_subs.end());
0480          std::fill(m_subs.begin(), m_subs.end(), v);
0481       }
0482       else
0483       {
0484          std::fill(m_subs.begin(), m_subs.end(), v);
0485          if(n+2 != len)
0486             m_subs.insert(m_subs.end(), n+2-len, v);
0487       }
0488       m_subs[1].first = i;
0489       m_last_closed_paren = 0;
0490    }
0491    void  set_base(BidiIterator pos)
0492    {
0493       m_base = pos;
0494    }
0495    BidiIterator base()const
0496    {
0497       return m_base;
0498    }
0499    void  set_first(BidiIterator i)
0500    {
0501       BOOST_REGEX_ASSERT(m_subs.size() > 2);
0502       // set up prefix:
0503       m_subs[1].second = i;
0504       m_subs[1].matched = (m_subs[1].first != i);
0505       // set up $0:
0506       m_subs[2].first = i;
0507       // zero out everything else:
0508       for(size_type n = 3; n < m_subs.size(); ++n)
0509       {
0510          m_subs[n].first = m_subs[n].second = m_subs[0].second;
0511          m_subs[n].matched = false;
0512       }
0513    }
0514    void  set_first(BidiIterator i, size_type pos, bool escape_k = false)
0515    {
0516       BOOST_REGEX_ASSERT(pos+2 < m_subs.size());
0517       if(pos || escape_k)
0518       {
0519          m_subs[pos+2].first = i;
0520          if(escape_k)
0521          {
0522             m_subs[1].second = i;
0523             m_subs[1].matched = (m_subs[1].first != m_subs[1].second);
0524          }
0525       }
0526       else
0527          set_first(i);
0528    }
0529    void  maybe_assign(const match_results<BidiIterator, Allocator>& m);
0530 
0531    void  set_named_subs(std::shared_ptr<named_sub_type> subs)
0532    {
0533       m_named_subs = subs;
0534    }
0535 
0536 private:
0537    //
0538    // Error handler called when an uninitialized match_results is accessed:
0539    //
0540    static void raise_logic_error()
0541    {
0542       std::logic_error e("Attempt to access an uninitialized boost::match_results<> class.");
0543 #ifndef BOOST_REGEX_STANDALONE
0544       boost::throw_exception(e);
0545 #else
0546       throw e;
0547 #endif
0548    }
0549 
0550 
0551    vector_type            m_subs;                      // subexpressions
0552    BidiIterator   m_base;                              // where the search started from
0553    sub_match<BidiIterator> m_null;                     // a null match
0554    std::shared_ptr<named_sub_type> m_named_subs;     // Shared copy of named subs in the regex object
0555    int m_last_closed_paren;                            // Last ) to be seen - used for formatting
0556    bool m_is_singular;                                 // True if our stored iterators are singular
0557 };
0558 
0559 template <class BidiIterator, class Allocator>
0560 void  match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
0561 {
0562    if(m_is_singular)
0563    {
0564       *this = m;
0565       return;
0566    }
0567    const_iterator p1, p2;
0568    p1 = begin();
0569    p2 = m.begin();
0570    //
0571    // Distances are measured from the start of *this* match, unless this isn't
0572    // a valid match in which case we use the start of the whole sequence.  Note that
0573    // no subsequent match-candidate can ever be to the left of the first match found.
0574    // This ensures that when we are using bidirectional iterators, that distances 
0575    // measured are as short as possible, and therefore as efficient as possible
0576    // to compute.  Finally note that we don't use the "matched" data member to test
0577    // whether a sub-expression is a valid match, because partial matches set this
0578    // to false for sub-expression 0.
0579    //
0580    BidiIterator l_end = this->suffix().second;
0581    BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first;
0582    difference_type len1 = 0;
0583    difference_type len2 = 0;
0584    difference_type base1 = 0;
0585    difference_type base2 = 0;
0586    std::size_t i;
0587    for(i = 0; i < size(); ++i, ++p1, ++p2)
0588    {
0589       //
0590       // Leftmost takes priority over longest; handle special cases
0591       // where distances need not be computed first (an optimisation
0592       // for bidirectional iterators: ensure that we don't accidently
0593       // compute the length of the whole sequence, as this can be really
0594       // expensive).
0595       //
0596       if(p1->first == l_end)
0597       {
0598          if(p2->first != l_end)
0599          {
0600             // p2 must be better than p1, and no need to calculate
0601             // actual distances:
0602             base1 = 1;
0603             base2 = 0;
0604             break;
0605          }
0606          else
0607          {
0608             // *p1 and *p2 are either unmatched or match end-of sequence,
0609             // either way no need to calculate distances:
0610             if((p1->matched == false) && (p2->matched == true))
0611                break;
0612             if((p1->matched == true) && (p2->matched == false))
0613                return;
0614             continue;
0615          }
0616       }
0617       else if(p2->first == l_end)
0618       {
0619          // p1 better than p2, and no need to calculate distances:
0620          return;
0621       }
0622       base1 = std::distance(l_base, p1->first);
0623       base2 = std::distance(l_base, p2->first);
0624       BOOST_REGEX_ASSERT(base1 >= 0);
0625       BOOST_REGEX_ASSERT(base2 >= 0);
0626       if(base1 < base2) return;
0627       if(base2 < base1) break;
0628 
0629       len1 = std::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
0630       len2 = std::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
0631       BOOST_REGEX_ASSERT(len1 >= 0);
0632       BOOST_REGEX_ASSERT(len2 >= 0);
0633       if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
0634          break;
0635       if((p1->matched == true) && (p2->matched == false))
0636          return;
0637    }
0638    if(i == size())
0639       return;
0640    if(base2 < base1)
0641       *this = m;
0642    else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
0643       *this = m;
0644 }
0645 
0646 template <class BidiIterator, class Allocator>
0647 void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b)
0648 {
0649    a.swap(b);
0650 }
0651 
0652 template <class charT, class traits, class BidiIterator, class Allocator>
0653 std::basic_ostream<charT, traits>&
0654    operator << (std::basic_ostream<charT, traits>& os,
0655                 const match_results<BidiIterator, Allocator>& s)
0656 {
0657    return (os << s.str());
0658 }
0659 
0660 #ifdef BOOST_REGEX_MSVC
0661 #pragma warning(pop)
0662 #endif
0663 } // namespace boost
0664 
0665 #endif
0666 
0667