155733a246ee7a05dd1b10bff927a8e247b89e88
[platform/upstream/libzypp.git] / zypp / sat / AttrMatcher.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/AttrMatcher.h
10  *
11 */
12 #ifndef ZYPP_SAT_ATTRMATCHER_H
13 #define ZYPP_SAT_ATTRMATCHER_H
14
15 extern "C"
16 {
17 struct _Datamatcher;
18 }
19
20 #include <iosfwd>
21 #include <string>
22
23 #include "zypp/base/PtrTypes.h"
24 #include "zypp/base/SafeBool.h"
25 #include "zypp/base/Exception.h"
26
27 ///////////////////////////////////////////////////////////////////
28 namespace zypp
29 { /////////////////////////////////////////////////////////////////
30
31   ///////////////////////////////////////////////////////////////////
32   //
33   //    CLASS NAME : Match
34   //
35   /** String matching option flags as used e.g. by \ref sat::AttrMatcher.
36    *
37    *
38    *
39    * \code
40    * Match mode( Match::GLOB | Match::NOCASE );
41    * \endcode
42    */
43   class Match : private base::SafeBool<Match>
44   {
45     private:
46       static const int _modemask;
47       static const int _flagmask;
48
49     public:
50       /** Mode flags (mutual exclusive). */
51       enum Mode
52       {
53         NOTHING,        //!< Match nothing
54         STRING,         //!< Excat matching
55         SUBSTRING,      //!< Match substring
56         GLOB,           //!< Glob
57         REGEX,          //!< Regular Expression
58         OTHER           //!< Something else.
59       };
60
61       /** \name Option flags
62        * Some flags are actually \ref sat::LookupAttr specific, as they tell
63        * how to retrieve the attribute values. The plain \ref sat::AttrMatcher
64        * will ignore those flags and use the ones related to string matching only
65        * (like \ref NOCASE).
66        */
67       //@{
68       /** If set, match case insensitive. */
69       static const Match NOCASE;
70       /** internal */
71       static const Match NO_STORAGE_SOLVABLE;
72       /** internal */
73       static const Match SUB;
74       /** internal */
75       static const Match ARRAYSENTINEL;
76       /** If set, skip any \c kind: prefix when looking at a \ref Solvable name. */
77       static const Match SKIP_KIND;
78       /**  If set, match full path when matching in filelists, otherwise just the basenames. */
79       static const Match FILES;
80       //@}
81
82     public:
83       /** Default ctor \c 0 or \ref NOTHING. */
84       Match()
85       : _val( 0 )
86       {}
87
88       /** Ctor from \ref Mode value. */
89       Match( Mode val_r )
90       : _val( modeval( val_r ) )
91       {}
92
93       /** Just in case one needs it. */
94       explicit Match( int val_r )
95       : _val( val_r )
96       {}
97
98 #ifndef SWIG // Swig treats it as syntax error
99       /** Evaluate in a boolean context <tt>( != 0 )</tt>. */
100       using base::SafeBool<Match>::operator bool_type;
101 #endif
102
103     public:
104       /** Test whether \c all of the \a rhs bits are set (same mode if \a rhs has one). */
105       bool test( const Match & rhs ) const
106       { return ( ( flagval() & rhs.flagval() ) == rhs.flagval() )
107           && ( !rhs.modeval() || rhs.modeval() == modeval() ); }
108
109       /** Whether at least one of the \a rhs bits is set (or the same mode). */
110       bool testAnyOf( const Match & rhs ) const
111       { return ( flagval() & rhs.flagval() )
112           || ( rhs.modeval() && rhs.modeval() == modeval() ); }
113
114       /** Set all of the \a rhs bits (setting a new mode if \a rhs has one). */
115       void set( const Match & rhs )
116       {
117         if ( rhs.modeval() )
118           _val = rhs._val | flagval(); // also set the rhs mode
119         else
120           _val |= rhs._val; // just set the flags
121       }
122
123       /** Unset all of the \a rhs bits (unsets mode if the same as \a rhs). */
124       void unset( const Match & rhs )
125       {
126         if ( modeval() == rhs.modeval() )
127           _val = flagval() & ~rhs.flagval(); // also unset mode
128         else
129           _val &= ~rhs.flagval(); // just unset falgs
130       }
131
132       /** Depending on the value of \a onoff, set or unset flags. */
133       void turn( const Match & rhs, bool onoff )
134       { onoff ? set( rhs ) : unset( rhs ); }
135
136       /** Add flags. */
137       Match & operator|=( const Match & rhs )
138       { set( rhs ); return *this; }
139
140       /** Remove flags.*/
141       Match & operator-=( const Match & rhs )
142       { unset( rhs ); return *this; }
143
144     public:
145       /** Return the \c mode part. */
146       Mode mode() const;
147
148       /** Return the \c flags part. */
149       Match flags() const
150       { return Match( flagval() ); }
151
152     public:
153       /** \name Low level integer representation. */
154       //@{
155       /** Return the integer representation. */
156       int get() const           { return _val; }
157       /** Return the modes integer representation. */
158       int modeval() const       { return _val & _modemask; }
159       /** Return the flags integer representation. */
160       int flagval() const       { return _val & _flagmask; }
161       //@}
162
163     public:
164       /** \name Mode flag manip/query convenience. */
165       //@{
166       /** Whether this has mode \a rhs */
167       bool isMode( Mode rhs ) const
168       { return modeval() == modeval( rhs ); }
169       /** Whether this has mode \ref STRING. */
170       bool isModeString() const
171       { return isMode( STRING ); }
172       /** Whether this has mode \ref SUBSTRING. */
173       bool isModeSubstring() const
174       { return isMode( SUBSTRING ); }
175       /** Whether this has mode \ref GLOB. */
176       bool isModeGlob() const
177       { return isMode( GLOB ); }
178       /** Whether this has mode \ref REGEX. */
179       bool isModeRegex() const
180       { return isMode( REGEX ); }
181
182       /** Set the mode part to \a rhs . */
183       void setMode( Mode rhs )
184       { _val = modeval( rhs ) | flagval(); }
185       /** Set the mode \ref STRING. */
186       void setModeString()
187       { setMode( STRING ); }
188       /** Set the mode \ref SUBSTRING. */
189       void setModeSubstring()
190       { setMode( SUBSTRING ); }
191       /** Set the mode \ref GLOB. */
192       void setModeGlob()
193       { setMode( GLOB ); }
194       /** Set the mode \ref REGEX. */
195       void setModeRegex()
196       { setMode( REGEX ); }
197       //@}
198
199       /** String representation. */
200       std::string asString() const;
201
202     private:
203       friend base::SafeBool<Match>::operator bool_type() const;
204       bool boolTest() const     { return _val; }
205
206       /** Numeric value for enum (short for <tt>Match(m).get()</tt>). */
207       static int modeval( Mode mode_r );
208
209     private:
210       int _val;
211   };
212
213   /** \relates Match */
214   inline bool operator==( const Match & lhs, const Match & rhs )
215   { return lhs.get() == rhs.get(); }
216   /** \relates Match */
217   inline bool operator!=( const Match & lhs, const Match & rhs )
218   { return lhs.get() != rhs.get(); }
219
220   /** \relates Match */
221   inline Match operator|( const Match & lhs, const Match & rhs )
222   { return Match(lhs) |= rhs; }
223   /** \relates Match \overload to disambiguate 'int|int'. */
224   inline Match operator|( Match::Mode lhs, Match::Mode rhs )
225   { return Match(lhs) |= rhs; }
226
227   /** \relates Match */
228   inline Match operator-( const Match & lhs, const Match & rhs )
229   { return Match(lhs) -= rhs; }
230   /** \relates Match \overload to disambiguate 'int-int'. */
231   inline Match operator-( Match::Mode lhs, Match::Mode rhs )
232   { return Match(lhs) -= rhs; }
233
234   /** \relates Match::Mode Stream output */
235   std::ostream & operator<<( std::ostream & str, Match::Mode obj );
236
237   /** \relates Match Stream output */
238   std::ostream & operator<<( std::ostream & str, const Match & obj );
239
240
241   ///////////////////////////////////////////////////////////////////
242
243   ///////////////////////////////////////////////////////////////////
244   //
245   //    CLASS NAME : MatchException
246   //
247   /** Exceptions thrown from attribute matching. */
248   struct MatchException : public Exception
249   {
250     /** Supplied message. */
251     explicit MatchException( const std::string & msg_r ) : Exception( msg_r ) {}
252   };
253
254   /** Unknown match mode. */
255   struct MatchUnknownModeException : public MatchException
256   {
257     /** Supplied message. */
258     explicit MatchUnknownModeException( const std::string & msg_r ) : MatchException( msg_r ) {}
259
260     /** Build message including the \a mode and optional the pattern string. */
261     MatchUnknownModeException( const Match & mode_r, const std::string & msg_r = std::string() );
262   };
263
264   /** Invalid regular expression (failed ::regcomp). */
265   struct MatchInvalidRegexException : public MatchException
266   {
267     /** Supplied message. */
268     explicit MatchInvalidRegexException( const std::string & msg_r ) : MatchException( msg_r ) {}
269
270     /** Build message including the \a regex and \c ::regcomp returncode (use \c 0 if unknown). */
271     MatchInvalidRegexException( const std::string & regex_r, int regcomp_r );
272   };
273
274   ///////////////////////////////////////////////////////////////////
275
276   ///////////////////////////////////////////////////////////////////
277   namespace sat
278   { /////////////////////////////////////////////////////////////////
279
280     ///////////////////////////////////////////////////////////////////
281     //
282     //  CLASS NAME : AttrMatcher
283     //
284     /** String matching (STRING|SUBSTRING|GLOB|REGEX).
285      *
286      * Used by e.g. \ref PoolQuery and \ref LookupAttr for queries,
287      * but it can also be used for matching arbitrary strings.
288      *
289      * \code
290      *  AttrMatcher matches( "foo" );
291      *  for_( it, stringlist.begin(), stringlist().end() )
292      *  {
293      *    if ( matches( *it ) )
294      *      cout << *it << " has substring 'foo'" << endl;
295      *  }
296      * \endcode
297      *
298      * \Note Those flags are always set: <tt>REG_EXTENDED | REG_NOSUB | REG_NEWLINE</tt>
299      */
300     class AttrMatcher : private base::SafeBool<AttrMatcher>
301     {
302       friend std::ostream & operator<<( std::ostream & str, const AttrMatcher & obj );
303
304       public:
305         typedef MatchException Exception;
306
307       public:
308         /** Implementation  */
309         class Impl;
310
311       public:
312         /** Default ctor matches nothing. */
313         AttrMatcher();
314
315         /** Ctor from string matches in \ref Match::STRING mode per default. */
316         AttrMatcher( const std::string & search_r );
317
318         /** Ctor taking string and \ref Match flags. */
319         AttrMatcher( const std::string & search_r, const Match & flags_r );
320
321         /** Low level interface wraps \a flags into \ref Match. */
322         AttrMatcher( const std::string & search_r, int flags_r );
323
324 #ifndef SWIG // Swig treats it as syntax error
325       /** Evaluate in a boolean context <tt>( ! searchstring().empty() )</tt>. */
326       using base::SafeBool<AttrMatcher>::operator bool_type;
327 #endif
328
329       public:
330         /** Return whether string matches.
331          * You can use it with any class that impements \c c_str.
332          * (\c std::string, \ref Pathname, \ref IdString, ...).
333          * \Note \c NULL never matches.
334          */
335         template<class _Tp>
336             bool operator()( const _Tp & string_r ) const
337         { return doMatch( string_r.c_str() ); }
338         /** \overload */
339         bool operator()( const char * string_r ) const
340         { return doMatch( string_r ); }
341
342       public:
343         /** The current searchstring. */
344         const std::string & searchstring() const;
345
346         /** Set a new searchstring. */
347         void setSearchstring( const std::string & string_r );
348
349         /** Set a new searchstring and flags. */
350         void setSearchstring( const std::string & string_r, const Match & flags_r );
351
352         /** The current search flags. */
353         const Match & flags() const;
354
355         /** Set new search flags. */
356         void setFlags( const Match & flags_r );
357
358       public:
359         /** Compile the pattern e.g. in case of \c REGEX.
360          * \throws MatchUnknownModeException If the \ref Match flag more than
361          *         one mode bit set.
362          * \throws MatchInvalidRegexException If \ref Match::REGEX is set
363          *         and \ref searchstring is not a valid regular expression.
364          */
365         void compile() const;
366
367         /** Whether the \ref AttrMatcher is already compiled. */
368         bool isCompiled() const;
369
370         /** Return whether string matches.
371          * Compiles the \ref AttrMatcher if this was not yet done.
372          * \throws MatchException Any of the exceptions thrown by \ref AttrMatcher::compile.
373          */
374         bool doMatch( const char * string_r ) const;
375
376       private:
377         friend base::SafeBool<AttrMatcher>::operator bool_type() const;
378         bool boolTest() const
379         { return !searchstring().empty(); }
380
381       private:
382         /** Pointer to implementation */
383         RWCOW_pointer<Impl> _pimpl;
384     };
385     ///////////////////////////////////////////////////////////////////
386
387     /** \relates AttrMatcher Stream output */
388     std::ostream & operator<<( std::ostream & str, const AttrMatcher & obj );
389
390     /////////////////////////////////////////////////////////////////
391   } // namespace sat
392   ///////////////////////////////////////////////////////////////////
393   /////////////////////////////////////////////////////////////////
394 } // namespace zypp
395 ///////////////////////////////////////////////////////////////////
396 #endif // ZYPP_SAT_ATTRMATCHER_H