libzypp  11.13.5
StrMatcher.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 extern "C"
13 {
14 #include <solv/repo.h>
15 }
16 
17 #include <iostream>
18 #include <sstream>
19 
20 #include "zypp/base/LogTools.h"
21 #include "zypp/base/Gettext.h"
22 #include "zypp/base/String.h"
23 
24 #include "zypp/base/StrMatcher.h"
25 
26 using std::endl;
27 
29 namespace zypp
30 {
32  // class Match
34 
35  const int Match::_modemask = SEARCH_STRINGMASK;
36  const int Match::_flagmask = ~_modemask;
37 
38  // option flags
39  const Match Match::NOCASE (SEARCH_NOCASE);
40 
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);
50 
52  {
53  switch ( modeval() )
54  {
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;
62  }
63  return OTHER;
64  }
65 
66  int Match::modeval( Mode mode_r )
67  {
68  switch ( mode_r )
69  {
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;
78  }
79  return SEARCH_STRINGMASK;
80  }
81 
82  std::string Match::asString() const
83  { std::ostringstream str; str << *this; return str.str(); }
84 
85  std::ostream & operator<<( std::ostream & str, Match::Mode obj )
86  {
87  switch ( obj )
88  {
89 #define OUTS(V) case Match::V: return str << #V; break
90  OUTS( NOTHING );
91  OUTS( STRING );
92  OUTS( STRINGSTART );
93  OUTS( STRINGEND );
94  OUTS( SUBSTRING );
95  OUTS( GLOB );
96  OUTS( REGEX );
97  OUTS( OTHER );
98 #undef OUTS
99  }
100  return str << "Match::Mode::UNKNOWN";
101  }
102 
103  std::ostream & operator<<( std::ostream & str, const Match & obj )
104  {
105  if ( ! obj )
106  return str << "NOTHING";
107 
108  const char * sep = "|";
109  Match::Mode mode( obj.mode() );
110  switch ( mode )
111  {
112  case Match::NOTHING:
113  sep = 0; // suppress 'NOTHING|'
114  break;
115  case Match::OTHER:
116  str << mode<<"("<<obj.modeval()<<")"; // check whether libsolv has introduced new modes!
117  break;
118  default:
119  str << mode;
120  break;
121  }
122 
123  int val = obj.flagval();
124  if ( val )
125  {
126 #define OUTS(V) if ( val & Match::V.get() ) { val &= ~Match::V.get(); if ( sep ) str << sep; else sep = "|"; str << #V; }
127  OUTS( NOCASE );
128  OUTS( NO_STORAGE_SOLVABLE );
129  OUTS( SUB );
130  OUTS( ARRAYSENTINEL );
131  OUTS( DISABLED_REPOS );
132  OUTS( COMPLETE_FILELIST );
133  OUTS( SKIP_KIND );
134  OUTS( FILES );
135  OUTS( CHECKSUMS );
136 #undef OUTS
137  if ( val )
138  {
139  if ( sep ) str << sep;
140  str << zypp::str::hexstring( val ); // check whether libsolv has introduced new flags.
141  }
142  }
143  return str;
144  }
145 
147  // class MatchException
149 
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() ) )
153  {}
154 
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() ) )
158  {}
159 
168  {
170  {}
171 
172  Impl( const std::string & search_r, const Match & flags_r )
173  : _search( search_r )
174  , _flags( flags_r )
175  {}
176 
178  { invalidate(); }
179 
181  void compile() const
182  {
183  if ( !_matcher )
184  {
185  if ( _flags.mode() == Match::OTHER )
187 
188  _matcher.reset( new ::_Datamatcher );
189  int res = ::datamatcher_init( _matcher.get(), _search.c_str(), _flags.get() );
190  if ( res )
191  {
192  _matcher.reset();
194  }
195  }
196  }
197 
199  bool isCompiled() const
200  { return _matcher; }
201 
203  bool doMatch( const char * string_r ) const
204  {
205  compile(); // nop if already compiled.
206 
207  if ( ! string_r )
208  return false; // NULL never matches
209  return ::datamatcher_match( _matcher.get(), string_r );
210  }
211 
213  const std::string & searchstring() const
214  { return _search; }
215 
217  void setSearchstring( const std::string & string_r )
218  { invalidate(); _search = string_r; }
219 
221  const Match & flags() const
222  { return _flags; }
223 
225  void setFlags( const Match & flags_r )
226  { invalidate(); _flags = flags_r; }
227 
228  private:
230  void invalidate()
231  {
232  if ( _matcher )
233  ::datamatcher_free( _matcher.get() );
234  _matcher.reset();
235  }
236 
237  private:
238  std::string _search;
240  mutable scoped_ptr< ::_Datamatcher> _matcher;
241 
242  private:
243  friend Impl * rwcowClone<Impl>( const Impl * rhs );
245  Impl * clone() const
246  { return new Impl( _search, _flags ); }
247  };
248 
250  inline std::ostream & operator<<( std::ostream & str, const StrMatcher::Impl & obj )
251  {
252  return str << "\"" << obj.searchstring() << "\"{" << obj.flags() << "}";
253  }
254 
256  // class StrMatcher
258 
260  : _pimpl( new Impl )
261  {}
262 
263  StrMatcher::StrMatcher( const std::string & search_r )
264  : _pimpl( new Impl( search_r, Match::STRING ) )
265  {}
266 
267  StrMatcher::StrMatcher( const std::string & search_r, const Match & flags_r )
268  : _pimpl( new Impl( search_r, flags_r ) )
269  {}
270 
271  StrMatcher::StrMatcher( const std::string & search_r, const Match::Mode & flags_r )
272  : _pimpl( new Impl( search_r, flags_r ) )
273  {}
274 
275  StrMatcher::StrMatcher( const std::string & search_r, int flags_r )
276  : _pimpl( new Impl( search_r, Match(flags_r) ) )
277  {}
278 
279  void StrMatcher::compile() const
280  { return _pimpl->compile(); }
281 
283  { return _pimpl->isCompiled(); }
284 
285  bool StrMatcher::doMatch( const char * string_r ) const
286  { return _pimpl->doMatch( string_r ); }
287 
288  const std::string & StrMatcher::searchstring() const
289  { return _pimpl->searchstring(); }
290 
291  void StrMatcher::setSearchstring( const std::string & string_r )
292  { _pimpl->setSearchstring( string_r ); }
293 
294  void StrMatcher::setSearchstring( const std::string & string_r, const Match & flags_r )
295  {
296  _pimpl->setSearchstring( string_r );
297  _pimpl->setFlags( flags_r );
298  }
299 
300  const Match & StrMatcher::flags() const
301  { return _pimpl->flags(); }
302 
303  void StrMatcher::setFlags( const Match & flags_r )
304  { _pimpl->setFlags( flags_r ); }
305 
306  std::ostream & operator<<( std::ostream & str, const StrMatcher & obj )
307  { return str << *obj._pimpl; }
308 
309  bool operator==( const StrMatcher & lhs, const StrMatcher & rhs )
310  {
311  return ( lhs.flags() == rhs.flags()
312  && lhs.searchstring() == rhs.searchstring() );
313  }
314 
315  bool operator<( const StrMatcher & lhs, const StrMatcher & rhs )
316  {
317  if ( lhs.flags().get() != rhs.flags().get() )
318  return ( lhs.flags().get() < rhs.flags().get() );
319 
320  return ( lhs.searchstring() < rhs.searchstring() );
321  }
322 
323 } // namespace zypp