libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 extern "C" 00013 { 00014 #include <solv/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 libsolv 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 libsolv 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