1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/StrMatcher.cc
14 #include <solv/repo.h>
20 #include "zypp/base/LogTools.h"
21 #include "zypp/base/Gettext.h"
22 #include "zypp/base/String.h"
24 #include "zypp/base/StrMatcher.h"
25 #include "zypp/sat/detail/PoolMember.h"
29 ///////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
36 const int Match::_modemask = SEARCH_STRINGMASK;
37 const int Match::_flagmask = ~_modemask;
40 const Match Match::NOCASE (SEARCH_NOCASE);
42 // sat::LookupAttr option flags
43 const Match Match::NO_STORAGE_SOLVABLE(SEARCH_NO_STORAGE_SOLVABLE);
44 const Match Match::SUB (SEARCH_SUB);
45 const Match Match::ARRAYSENTINEL (SEARCH_ARRAYSENTINEL);
46 const Match Match::DISABLED_REPOS (SEARCH_DISABLED_REPOS);
47 const Match Match::COMPLETE_FILELIST (SEARCH_COMPLETE_FILELIST);
48 const Match Match::SKIP_KIND (SEARCH_SKIP_KIND);
49 const Match Match::FILES (SEARCH_FILES);
50 const Match Match::CHECKSUMS (SEARCH_CHECKSUMS);
52 Match::Mode Match::mode() const
56 case 0: return NOTHING; break;
57 case SEARCH_STRING: return STRING; break;
58 case SEARCH_STRINGSTART: return STRINGSTART; break;
59 case SEARCH_STRINGEND: return STRINGEND; break;
60 case SEARCH_SUBSTRING: return SUBSTRING; break;
61 case SEARCH_GLOB: return GLOB; break;
62 case SEARCH_REGEX: return REGEX; break;
67 int Match::modeval( Mode mode_r )
71 case NOTHING: return 0; break;
72 case STRING: return SEARCH_STRING; break;
73 case STRINGSTART: return SEARCH_STRINGSTART; break;
74 case STRINGEND: return SEARCH_STRINGEND; break;
75 case SUBSTRING: return SEARCH_SUBSTRING; break;
76 case GLOB: return SEARCH_GLOB; break;
77 case REGEX: return SEARCH_REGEX; break;
78 case OTHER: return SEARCH_STRINGMASK; break;
80 return SEARCH_STRINGMASK;
83 std::string Match::asString() const
84 { std::ostringstream str; str << *this; return str.str(); }
86 std::ostream & operator<<( std::ostream & str, Match::Mode obj )
90 #define OUTS(V) case Match::V: return str << #V; break
101 return str << "Match::Mode::UNKNOWN";
104 std::ostream & operator<<( std::ostream & str, const Match & obj )
107 return str << "NOTHING";
109 const char * sep = "|";
110 Match::Mode mode( obj.mode() );
114 sep = 0; // suppress 'NOTHING|'
117 str << mode<<"("<<obj.modeval()<<")"; // check whether libsolv has introduced new modes!
124 int val = obj.flagval();
127 #define OUTS(V) if ( val & Match::V.get() ) { val &= ~Match::V.get(); if ( sep ) str << sep; else sep = "|"; str << #V; }
129 OUTS( NO_STORAGE_SOLVABLE );
131 OUTS( ARRAYSENTINEL );
132 OUTS( DISABLED_REPOS );
133 OUTS( COMPLETE_FILELIST );
140 if ( sep ) str << sep;
141 str << zypp::str::hexstring( val ); // check whether libsolv has introduced new flags.
147 ///////////////////////////////////////////////////////////////////
148 // class MatchException
149 ///////////////////////////////////////////////////////////////////
151 MatchUnknownModeException::MatchUnknownModeException( const Match & mode_r, const std::string & msg_r )
152 : MatchException( msg_r.empty() ? str::form(_("Unknown match mode '%s'"), mode_r.asString().c_str() )
153 : str::form(_("Unknown match mode '%s' for pattern '%s'"), mode_r.asString().c_str(), msg_r.c_str() ) )
156 MatchInvalidRegexException::MatchInvalidRegexException( const std::string & regex_r, int regcomp_r )
157 : MatchException( regcomp_r ? str::form(_("Invalid regular expression '%s': regcomp returned %d"), regex_r.c_str(), regcomp_r )
158 : str::form(_("Invalid regular expression '%s'"), regex_r.c_str() ) )
161 ///////////////////////////////////////////////////////////////////
162 /// \class StrMatcher::Impl
163 /// \brief StrMatcher implementation.
165 /// \note Take care to release any allocated regex by calling
166 /// \c ::datamatcher_free.
167 ///////////////////////////////////////////////////////////////////
168 struct StrMatcher::Impl
173 Impl( std::string search_r, const Match & flags_r )
174 : _search( std::move(search_r) )
181 /** Compile the pattern. */
186 if ( _flags.mode() == Match::OTHER )
187 ZYPP_THROW( MatchUnknownModeException( _flags, _search ) );
189 _matcher.reset( new sat::detail::CDatamatcher );
190 int res = ::datamatcher_init( _matcher.get(), _search.c_str(), _flags.get() );
194 ZYPP_THROW( MatchInvalidRegexException( _search, res ) );
199 /** Whether the pattern is already compiled. */
200 bool isCompiled() const
201 { return _matcher != nullptr; }
203 /** Return whether string matches. */
204 bool doMatch( const char * string_r ) const
206 compile(); // nop if already compiled.
209 return false; // NULL never matches
210 return ::datamatcher_match( _matcher.get(), string_r );
213 /** The current searchstring. */
214 const std::string & searchstring() const
217 /** Set a new searchstring. */
218 void setSearchstring( std::string string_r )
219 { invalidate(); _search = std::move(string_r); }
221 /** The current search flags. */
222 const Match & flags() const
225 /** Set new search flags. */
226 void setFlags( const Match & flags_r )
227 { invalidate(); _flags = flags_r; }
230 /** Has to be called if _search or _flags change. */
234 ::datamatcher_free( _matcher.get() );
241 mutable scoped_ptr< sat::detail::CDatamatcher> _matcher;
244 friend Impl * rwcowClone<Impl>( const Impl * rhs );
245 /** clone for RWCOW_pointer */
247 { return new Impl( _search, _flags ); }
250 /** \relates StrMatcher::Impl Stream output */
251 inline std::ostream & operator<<( std::ostream & str, const StrMatcher::Impl & obj )
253 return str << "\"" << obj.searchstring() << "\"{" << obj.flags() << "}";
256 ///////////////////////////////////////////////////////////////////
258 ///////////////////////////////////////////////////////////////////
260 StrMatcher::StrMatcher()
264 StrMatcher::StrMatcher( const std::string & search_r )
265 : _pimpl( new Impl( search_r, Match::STRING ) )
267 StrMatcher::StrMatcher( std::string && search_r )
268 : _pimpl( new Impl( std::move(search_r), Match::STRING ) )
271 StrMatcher::StrMatcher( const std::string & search_r, const Match & flags_r )
272 : _pimpl( new Impl( search_r, flags_r ) )
274 StrMatcher::StrMatcher( std::string && search_r, const Match & flags_r )
275 : _pimpl( new Impl( std::move(search_r), flags_r ) )
278 StrMatcher::StrMatcher( const std::string & search_r, const Match::Mode & flags_r )
279 : _pimpl( new Impl( search_r, flags_r ) )
281 StrMatcher::StrMatcher( std::string && search_r, const Match::Mode & flags_r )
282 : _pimpl( new Impl( std::move(search_r), flags_r ) )
285 StrMatcher::StrMatcher( const std::string & search_r, int flags_r )
286 : _pimpl( new Impl( search_r, Match(flags_r) ) )
288 StrMatcher::StrMatcher( std::string && search_r, int flags_r )
289 : _pimpl( new Impl( std::move(search_r), Match(flags_r) ) )
292 void StrMatcher::compile() const
293 { return _pimpl->compile(); }
295 bool StrMatcher::isCompiled() const
296 { return _pimpl->isCompiled(); }
298 bool StrMatcher::doMatch( const char * string_r ) const
299 { return _pimpl->doMatch( string_r ); }
301 const std::string & StrMatcher::searchstring() const
302 { return _pimpl->searchstring(); }
304 void StrMatcher::setSearchstring( const std::string & string_r )
305 { _pimpl->setSearchstring( string_r ); }
306 void StrMatcher::setSearchstring( std::string && string_r )
307 { _pimpl->setSearchstring( std::move(string_r) ); }
309 void StrMatcher::setSearchstring( const std::string & string_r, const Match & flags_r )
311 _pimpl->setSearchstring( string_r );
312 _pimpl->setFlags( flags_r );
314 void StrMatcher::setSearchstring( std::string && string_r, const Match & flags_r )
316 _pimpl->setSearchstring( std::move(string_r) );
317 _pimpl->setFlags( flags_r );
320 const Match & StrMatcher::flags() const
321 { return _pimpl->flags(); }
323 void StrMatcher::setFlags( const Match & flags_r )
324 { _pimpl->setFlags( flags_r ); }
326 std::ostream & operator<<( std::ostream & str, const StrMatcher & obj )
327 { return str << *obj._pimpl; }
329 bool operator==( const StrMatcher & lhs, const StrMatcher & rhs )
331 return ( lhs.flags() == rhs.flags()
332 && lhs.searchstring() == rhs.searchstring() );
335 bool operator<( const StrMatcher & lhs, const StrMatcher & rhs )
337 if ( lhs.flags().get() != rhs.flags().get() )
338 return ( lhs.flags().get() < rhs.flags().get() );
340 return ( lhs.searchstring() < rhs.searchstring() );
344 ///////////////////////////////////////////////////////////////////