AttrMatcher.cc
Go to the documentation of this file.00001
00002
00003
00004
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
00036
00038
00039 const int Match::_modemask = SEARCH_STRINGMASK;
00040 const int Match::_flagmask = ~_modemask;
00041
00042
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;
00113 break;
00114 case Match::OTHER:
00115 str << mode<<"("<<obj.modeval()<<")";
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 );
00137 }
00138 }
00139 return str;
00140 }
00141
00143
00144
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
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();
00210
00211 if ( ! string_r )
00212 return false;
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
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
00316
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 }
00341 }