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"
28 ///////////////////////////////////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////
35 const int Match::_modemask = SEARCH_STRINGMASK;
36 const int Match::_flagmask = ~_modemask;
39 const Match Match::NOCASE (SEARCH_NOCASE);
41 // sat::LookupAttr option flags
42 const Match Match::NO_STORAGE_SOLVABLE(SEARCH_NO_STORAGE_SOLVABLE);
43 const Match Match::SUB (SEARCH_SUB);
44 const Match Match::ARRAYSENTINEL (SEARCH_ARRAYSENTINEL);
45 const Match Match::DISABLED_REPOS (SEARCH_DISABLED_REPOS);
46 const Match Match::COMPLETE_FILELIST (SEARCH_COMPLETE_FILELIST);
47 const Match Match::SKIP_KIND (SEARCH_SKIP_KIND);
48 const Match Match::FILES (SEARCH_FILES);
49 const Match Match::CHECKSUMS (SEARCH_CHECKSUMS);
51 Match::Mode Match::mode() const
55 case 0: return NOTHING; break;
56 case SEARCH_STRING: return STRING; break;
57 case SEARCH_STRINGSTART: return STRINGSTART; break;
58 case SEARCH_STRINGEND: return STRINGEND; break;
59 case SEARCH_SUBSTRING: return SUBSTRING; break;
60 case SEARCH_GLOB: return GLOB; break;
61 case SEARCH_REGEX: return REGEX; break;
66 int Match::modeval( Mode mode_r )
70 case NOTHING: return 0; break;
71 case STRING: return SEARCH_STRING; break;
72 case STRINGSTART: return SEARCH_STRINGSTART; break;
73 case STRINGEND: return SEARCH_STRINGEND; break;
74 case SUBSTRING: return SEARCH_SUBSTRING; break;
75 case GLOB: return SEARCH_GLOB; break;
76 case REGEX: return SEARCH_REGEX; break;
77 case OTHER: return SEARCH_STRINGMASK; break;
79 return SEARCH_STRINGMASK;
82 std::string Match::asString() const
83 { std::ostringstream str; str << *this; return str.str(); }
85 std::ostream & operator<<( std::ostream & str, Match::Mode obj )
89 #define OUTS(V) case Match::V: return str << #V; break
100 return str << "Match::Mode::UNKNOWN";
103 std::ostream & operator<<( std::ostream & str, const Match & obj )
106 return str << "NOTHING";
108 const char * sep = "|";
109 Match::Mode mode( obj.mode() );
113 sep = 0; // suppress 'NOTHING|'
116 str << mode<<"("<<obj.modeval()<<")"; // check whether libsolv has introduced new modes!
123 int val = obj.flagval();
126 #define OUTS(V) if ( val & Match::V.get() ) { val &= ~Match::V.get(); if ( sep ) str << sep; else sep = "|"; str << #V; }
128 OUTS( NO_STORAGE_SOLVABLE );
130 OUTS( ARRAYSENTINEL );
131 OUTS( DISABLED_REPOS );
132 OUTS( COMPLETE_FILELIST );
139 if ( sep ) str << sep;
140 str << zypp::str::hexstring( val ); // check whether libsolv has introduced new flags.
146 ///////////////////////////////////////////////////////////////////
147 // class MatchException
148 ///////////////////////////////////////////////////////////////////
150 MatchUnknownModeException::MatchUnknownModeException( const Match & mode_r, const std::string & msg_r )
151 : MatchException( msg_r.empty() ? str::form(_("Unknown match mode '%s'"), mode_r.asString().c_str() )
152 : str::form(_("Unknown match mode '%s' for pattern '%s'"), mode_r.asString().c_str(), msg_r.c_str() ) )
155 MatchInvalidRegexException::MatchInvalidRegexException( const std::string & regex_r, int regcomp_r )
156 : MatchException( regcomp_r ? str::form(_("Invalid regular expression '%s': regcomp returned %d"), regex_r.c_str(), regcomp_r )
157 : str::form(_("Invalid regular expression '%s'"), regex_r.c_str() ) )
160 ///////////////////////////////////////////////////////////////////
161 /// \class StrMatcher::Impl
162 /// \brief StrMatcher implementation.
164 /// \note Take care to release any allocated regex by calling
165 /// \c ::datamatcher_free.
166 ///////////////////////////////////////////////////////////////////
167 struct StrMatcher::Impl
172 Impl( const std::string & search_r, const Match & flags_r )
173 : _search( search_r )
180 /** Compile the pattern. */
185 if ( _flags.mode() == Match::OTHER )
186 ZYPP_THROW( MatchUnknownModeException( _flags, _search ) );
188 _matcher.reset( new ::_Datamatcher );
189 int res = ::datamatcher_init( _matcher.get(), _search.c_str(), _flags.get() );
193 ZYPP_THROW( MatchInvalidRegexException( _search, res ) );
198 /** Whether the pattern is already compiled. */
199 bool isCompiled() const
200 { return _matcher != nullptr; }
202 /** Return whether string matches. */
203 bool doMatch( const char * string_r ) const
205 compile(); // nop if already compiled.
208 return false; // NULL never matches
209 return ::datamatcher_match( _matcher.get(), string_r );
212 /** The current searchstring. */
213 const std::string & searchstring() const
216 /** Set a new searchstring. */
217 void setSearchstring( const std::string & string_r )
218 { invalidate(); _search = string_r; }
220 /** The current search flags. */
221 const Match & flags() const
224 /** Set new search flags. */
225 void setFlags( const Match & flags_r )
226 { invalidate(); _flags = flags_r; }
229 /** Has to be called if _search or _flags change. */
233 ::datamatcher_free( _matcher.get() );
240 mutable scoped_ptr< ::_Datamatcher> _matcher;
243 friend Impl * rwcowClone<Impl>( const Impl * rhs );
244 /** clone for RWCOW_pointer */
246 { return new Impl( _search, _flags ); }
249 /** \relates StrMatcher::Impl Stream output */
250 inline std::ostream & operator<<( std::ostream & str, const StrMatcher::Impl & obj )
252 return str << "\"" << obj.searchstring() << "\"{" << obj.flags() << "}";
255 ///////////////////////////////////////////////////////////////////
257 ///////////////////////////////////////////////////////////////////
259 StrMatcher::StrMatcher()
263 StrMatcher::StrMatcher( const std::string & search_r )
264 : _pimpl( new Impl( search_r, Match::STRING ) )
267 StrMatcher::StrMatcher( const std::string & search_r, const Match & flags_r )
268 : _pimpl( new Impl( search_r, flags_r ) )
271 StrMatcher::StrMatcher( const std::string & search_r, const Match::Mode & flags_r )
272 : _pimpl( new Impl( search_r, flags_r ) )
275 StrMatcher::StrMatcher( const std::string & search_r, int flags_r )
276 : _pimpl( new Impl( search_r, Match(flags_r) ) )
279 void StrMatcher::compile() const
280 { return _pimpl->compile(); }
282 bool StrMatcher::isCompiled() const
283 { return _pimpl->isCompiled(); }
285 bool StrMatcher::doMatch( const char * string_r ) const
286 { return _pimpl->doMatch( string_r ); }
288 const std::string & StrMatcher::searchstring() const
289 { return _pimpl->searchstring(); }
291 void StrMatcher::setSearchstring( const std::string & string_r )
292 { _pimpl->setSearchstring( string_r ); }
294 void StrMatcher::setSearchstring( const std::string & string_r, const Match & flags_r )
296 _pimpl->setSearchstring( string_r );
297 _pimpl->setFlags( flags_r );
300 const Match & StrMatcher::flags() const
301 { return _pimpl->flags(); }
303 void StrMatcher::setFlags( const Match & flags_r )
304 { _pimpl->setFlags( flags_r ); }
306 std::ostream & operator<<( std::ostream & str, const StrMatcher & obj )
307 { return str << *obj._pimpl; }
309 bool operator==( const StrMatcher & lhs, const StrMatcher & rhs )
311 return ( lhs.flags() == rhs.flags()
312 && lhs.searchstring() == rhs.searchstring() );
315 bool operator<( const StrMatcher & lhs, const StrMatcher & rhs )
317 if ( lhs.flags().get() != rhs.flags().get() )
318 return ( lhs.flags().get() < rhs.flags().get() );
320 return ( lhs.searchstring() < rhs.searchstring() );
324 ///////////////////////////////////////////////////////////////////