AttrMatcher.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 extern "C"
00013 {
00014 #include <satsolver/repo.h>
00015 }
00016 
00017 #include <iostream>
00018 #include <sstream>
00019 #include <boost/mpl/int.hpp>
00020 
00021 #include "zypp/base/LogTools.h"
00022 #include "zypp/base/Gettext.h"
00023 #include "zypp/base/String.h"
00024 
00025 #include "zypp/sat/AttrMatcher.h"
00026 
00027 using std::endl;
00028 
00030 namespace zypp
00031 { 
00032 
00034   //
00035   //    CLASS NAME : Match
00036   //
00038 
00039   const int Match::_modemask = SEARCH_STRINGMASK;
00040   const int Match::_flagmask = ~_modemask;
00041 
00042   // option flags
00043   const Match Match::NOCASE             (SEARCH_NOCASE);
00044   const Match Match::NO_STORAGE_SOLVABLE(SEARCH_NO_STORAGE_SOLVABLE);
00045   const Match Match::SUB                (SEARCH_SUB);
00046   const Match Match::ARRAYSENTINEL      (SEARCH_ARRAYSENTINEL);
00047   const Match Match::SKIP_KIND          (SEARCH_SKIP_KIND);
00048   const Match Match::FILES              (SEARCH_FILES);
00049 
00050   Match::Mode Match::mode() const
00051   {
00052     switch ( modeval() )
00053     {
00054       case 0:                   return NOTHING;         break;
00055       case SEARCH_STRING:       return STRING;          break;
00056       case SEARCH_STRINGSTART:  return STRINGSTART;     break;
00057       case SEARCH_STRINGEND:    return STRINGEND;       break;
00058       case SEARCH_SUBSTRING:    return SUBSTRING;       break;
00059       case SEARCH_GLOB:         return GLOB;            break;
00060       case SEARCH_REGEX:        return REGEX;           break;
00061     }
00062     return OTHER;
00063   }
00064 
00065   int Match::modeval( Mode mode_r )
00066   {
00067     switch ( mode_r )
00068     {
00069       case NOTHING:     return 0;                       break;
00070       case STRING:      return SEARCH_STRING;           break;
00071       case STRINGSTART: return SEARCH_STRINGSTART;      break;
00072       case STRINGEND:   return SEARCH_STRINGEND;        break;
00073       case SUBSTRING:   return SEARCH_SUBSTRING;        break;
00074       case GLOB:        return SEARCH_GLOB;             break;
00075       case REGEX:       return SEARCH_REGEX;            break;
00076       case OTHER:       return SEARCH_STRINGMASK;       break;
00077     }
00078     return SEARCH_STRINGMASK;
00079   }
00080 
00081   std::string Match::asString() const
00082   { std::ostringstream str; str << *this; return str.str(); }
00083 
00084   std::ostream & operator<<( std::ostream & str, Match::Mode obj )
00085   {
00086     switch ( obj )
00087     {
00088 #define OUTS(V) case Match::V: return str << #V; break
00089       OUTS( NOTHING );
00090       OUTS( STRING );
00091       OUTS( STRINGSTART );
00092       OUTS( STRINGEND );
00093       OUTS( SUBSTRING );
00094       OUTS( GLOB );
00095       OUTS( REGEX );
00096       OUTS( OTHER );
00097 #undef OUTS
00098     }
00099     return str << "Match::Mode::UNKNOWN";
00100   }
00101 
00102   std::ostream & operator<<( std::ostream & str, const Match & obj )
00103   {
00104     if ( ! obj )
00105       return str << "NOTHING";
00106 
00107     const char * sep = "|";
00108     Match::Mode mode( obj.mode() );
00109     switch ( mode )
00110     {
00111       case Match::NOTHING:
00112         sep = 0; // suppress 'NOTHING|'
00113         break;
00114       case Match::OTHER:
00115         str << mode<<"("<<obj.modeval()<<")"; // check whether satsolver has introduced new modes!
00116         break;
00117       default:
00118         str << mode;
00119         break;
00120     }
00121 
00122     int val = obj.flagval();
00123     if ( val )
00124     {
00125 #define OUTS(V) if ( val & Match::V.get() ) { val &= ~Match::V.get(); if ( sep ) str << sep; else sep = "|"; str << #V; }
00126       OUTS( NOCASE );
00127       OUTS( NO_STORAGE_SOLVABLE );
00128       OUTS( SUB );
00129       OUTS( ARRAYSENTINEL );
00130       OUTS( SKIP_KIND );
00131       OUTS( FILES );
00132 #undef OUTS
00133       if ( val )
00134       {
00135         if ( sep ) str << sep;
00136         str << zypp::str::hexstring( val ); // check whether satsolver has introduced new flags.
00137       }
00138     }
00139     return str;
00140   }
00141 
00143   //
00144   //    CLASS NAME : MatchException
00145   //
00147 
00148   MatchUnknownModeException::MatchUnknownModeException( const Match & mode_r, const std::string & msg_r )
00149   : MatchException( msg_r.empty() ? str::form(_("Unknown match mode '%s'"), mode_r.asString().c_str() )
00150                                   : str::form(_("Unknown match mode '%s' for pattern '%s'"), mode_r.asString().c_str(), msg_r.c_str() ) )
00151   {}
00152 
00153   MatchInvalidRegexException::MatchInvalidRegexException( const std::string & regex_r, int regcomp_r )
00154   : MatchException( regcomp_r ? str::form(_("Invalid regular expression '%s': regcomp returned %d"), regex_r.c_str(), regcomp_r )
00155                               : str::form(_("Invalid regular expression '%s'"), regex_r.c_str() ) )
00156   {}
00157 
00159   namespace sat
00160   { 
00161 
00163     //
00164     //  CLASS NAME : AttrMatcher::Impl
00165     //
00171     struct AttrMatcher::Impl
00172     {
00173       Impl()
00174       {}
00175 
00176       Impl( const std::string & search_r, const Match & flags_r )
00177         : _search( search_r )
00178         , _flags( flags_r )
00179       {}
00180 
00181       ~Impl()
00182       { invalidate(); }
00183 
00185       void compile() const
00186       {
00187         if ( !_matcher )
00188         {
00189           if ( _flags.mode() == Match::OTHER )
00190             ZYPP_THROW( MatchUnknownModeException( _flags, _search ) );
00191 
00192           _matcher.reset( new ::_Datamatcher );
00193           int res = ::datamatcher_init( _matcher.get(), _search.c_str(), _flags.get() );
00194           if ( res )
00195           {
00196             _matcher.reset();
00197             ZYPP_THROW( MatchInvalidRegexException( _search, res ) );
00198           }
00199         }
00200       }
00201 
00203       bool isCompiled() const
00204       { return _matcher; }
00205 
00207       bool doMatch( const char * string_r ) const
00208       {
00209         compile(); // nop if already compiled.
00210 
00211         if ( ! string_r )
00212           return false; // NULL never matches
00213         return ::datamatcher_match( _matcher.get(), string_r );
00214       }
00215 
00217       const std::string & searchstring() const
00218       { return _search; }
00219 
00221       void setSearchstring( const std::string & string_r )
00222       { invalidate(); _search = string_r; }
00223 
00225       const Match & flags() const
00226       { return _flags; }
00227 
00229       void setFlags( const Match & flags_r )
00230       { invalidate(); _flags = flags_r; }
00231 
00232       private:
00234         void invalidate()
00235         {
00236           if ( _matcher )
00237             ::datamatcher_free( _matcher.get() );
00238           _matcher.reset();
00239         }
00240 
00241       private:
00242         std::string _search;
00243         Match       _flags;
00244         mutable scoped_ptr< ::_Datamatcher> _matcher;
00245 
00246       private:
00247         friend Impl * rwcowClone<Impl>( const Impl * rhs );
00249         Impl * clone() const
00250         { return new Impl( _search, _flags ); }
00251     };
00253 
00255     inline std::ostream & operator<<( std::ostream & str, const AttrMatcher::Impl & obj )
00256     {
00257       return str << "\"" << obj.searchstring() << "\"{" << obj.flags() << "}";
00258     }
00259 
00261     //
00262     //  CLASS NAME : AttrMatcher
00263     //
00265 
00266     AttrMatcher::AttrMatcher()
00267     : _pimpl( new Impl )
00268     {}
00269 
00270     AttrMatcher::AttrMatcher( const std::string & search_r )
00271     : _pimpl( new Impl( search_r, Match::STRING ) )
00272     {}
00273 
00274     AttrMatcher::AttrMatcher( const std::string & search_r, const Match & flags_r )
00275     : _pimpl( new Impl( search_r, flags_r ) )
00276     {}
00277 
00278     AttrMatcher::AttrMatcher( const std::string & search_r, const Match::Mode & flags_r )
00279     : _pimpl( new Impl( search_r, flags_r ) )
00280     {}
00281 
00282     AttrMatcher::AttrMatcher( const std::string & search_r, int flags_r )
00283     : _pimpl( new Impl( search_r, Match(flags_r) ) )
00284     {}
00285 
00286     void AttrMatcher::compile() const
00287     { return _pimpl->compile(); }
00288 
00289     bool AttrMatcher::isCompiled() const
00290     { return _pimpl->isCompiled(); }
00291 
00292     bool AttrMatcher::doMatch( const char * string_r ) const
00293     { return _pimpl->doMatch( string_r ); }
00294 
00295     const std::string & AttrMatcher::searchstring() const
00296     { return _pimpl->searchstring(); }
00297 
00298     void AttrMatcher::setSearchstring( const std::string & string_r )
00299     { _pimpl->setSearchstring( string_r ); }
00300 
00301     void AttrMatcher::setSearchstring( const std::string & string_r, const Match & flags_r )
00302     {
00303       _pimpl->setSearchstring( string_r );
00304       _pimpl->setFlags( flags_r );
00305     }
00306 
00307     const Match & AttrMatcher::flags() const
00308     { return _pimpl->flags(); }
00309 
00310     void AttrMatcher::setFlags( const Match & flags_r )
00311     { _pimpl->setFlags( flags_r ); }
00312 
00313     /******************************************************************
00314     **
00315     **  FUNCTION NAME : operator<<
00316     **  FUNCTION TYPE : std::ostream &
00317     */
00318     std::ostream & operator<<( std::ostream & str, const AttrMatcher & obj )
00319     {
00320       return str << *obj._pimpl;
00321     }
00322 
00323     bool operator==( const AttrMatcher & lhs, const AttrMatcher & rhs )
00324     {
00325       return ( lhs.flags() == rhs.flags()
00326                && lhs.searchstring() == rhs.searchstring() );
00327     }
00328 
00329     bool operator<( const AttrMatcher & lhs, const AttrMatcher & rhs )
00330     {
00331       if ( lhs.flags().get() != rhs.flags().get() )
00332         return ( lhs.flags().get() < rhs.flags().get() );
00333 
00334       return ( lhs.searchstring() < rhs.searchstring() );
00335     }
00336 
00338   } // namespace sat
00341 } // namespace zypp

doxygen