Re: [Boost-bugs] [Boost C++ Libraries] #12959: Regex class negation

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #12959: Regex class negation
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2017-04-11 22:36:06


#12959: Regex class negation
-------------------------------+-------------------------
  Reporter: robic@… | Owner: johnmaddock
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: regex
   Version: Boost 1.61.0 | Severity: Showstopper
Resolution: | Keywords:
-------------------------------+-------------------------

Comment (by robic@…):

 A solution could be to keep a vector of individual class[[BR]]
 instead of a mask for all classes ''cnclasses''[[BR]]

 '''Only in a negated class, and only negative classes need to be
 tracked.[[BR]]'''
 The rest remains unchanged.

 Something like this works (tested):[[BR]]

 <boost\regex\v4\basic_regex_creator.hpp>[[BR]]


 {{{
 template <class charT, class traits>
 class basic_char_set
 {
   private:
   std::vector<unsigned __int64> m_NegNeg_Class;

 public:

    typedef typename std::vector<uint64_t>::const_iterator
 cNNclass_list_iterator;
    bool has_NegNegClasses()const
    {
       return m_NegNeg_Class.size() > 0 ? true : false;
    }
    cNNclass_list_iterator cn_begin()const
    {
       return m_NegNeg_Class.begin();
    }
    cNNclass_list_iterator cn_end()const
    {
       return m_NegNeg_Class.end();
    }

    void add_negated_class(m_type m)
    {
       if ( m_negate )
       {
         // if it's not already there, add it ..
         bool bDoAdd = true;

         for ( int i = 0; i < m_NegNeg_Class.size(); i++ )
         {
            if ( m_NegNeg_Class[i] == (unsigned __int64)m )
            {
              bDoAdd = false;
              break;
            }
         }
         if ( bDoAdd )
            m_NegNeg_Class.insert( m_NegNeg_Class.end(), (unsigned
 __int64)m );
       }
       else
          m_negated_classes |= m;
       m_empty = false;
    }
 }

 template <class charT, class traits>
 re_syntax_base* basic_regex_creator<charT, traits>::append_set(
    const basic_char_set<charT, traits>& char_set, mpl::false_*)
 {
    typedef typename basic_char_set<uint64_t, traits>::prop_list_iterator
 cNegNegClas_item_iterator;

    result->cNegNegClasses = 0;
    if ( char_set.is_negated() )
    {
       result->cNegNegClasses =
 static_cast<uint32_t>(::boost::BOOST_REGEX_DETAIL_NS::distance(char_set.cn_begin(),
 char_set.cn_end()));
    }

    //
    // now extend with all the negated negative character classes:
    //
    if ( result->isnot == true )
    {
       cNegNegClas_item_iterator cnfirst, cnlast;

       cnfirst = char_set.cn_begin();
       cnlast = char_set.cn_end();

       while(cnfirst != cnlast)
       {
          uint64_t* p =
 static_cast<uint64_t*>(this->m_pdata->m_data.extend(sizeof(uint64_t) *
 1));
          p[0] = *cnfirst;

          if(flags() & regbase::icase)
          {
             // adjust class as needed:
             if(((p[0] & m_lower_mask) == m_lower_mask) || ((p[0] &
 m_upper_mask) == m_upper_mask))
                p[0] |= m_alpha_mask;
          }
          ++cnfirst;
       }
    }
 }

 }}}

 <boost\regex\v4\perl_matcher.hpp>


 {{{
 template <class iterator, class charT, class traits_type, class
 char_classT>
 iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
                           iterator last,
                           const re_set_long<char_classT>* set_,
                           const regex_data<charT, traits_type>& e, bool
 icase)
 {

    // try and match a single character from the neg-neg classes
    if ( set_->cNegNegClasses && set_->isnot )
    {
        for(i = 0; i < set_->cNegNegClasses; i++)
        {
           uint64_t mask = *((uint64_t*)p);
           if(traits_inst.isctype(col, (mask_type)mask) == false)
              return set_->isnot ? next : ++next;
           p += (sizeof(uint64_t*) / sizeof(charT));
        }
    }

    // the rest unchanged
    if( set_->cclasses != 0 )
    {
       if(traits_inst.isctype(col, set_->cclasses) == true)
          return set_->isnot ? next : ++next;
    }

    if( set_->cnclasses != 0 )
    {
        if(traits_inst.isctype(col, set_->cnclasses) == false)
          return set_->isnot ? next : ++next;
    }
    return set_->isnot ? ++next : next;
 }
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12959#comment:1>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-04-11 22:39:09 UTC