- Added some doc and example how to use ResFilters to
[platform/upstream/libzypp.git] / zypp / ResFilters.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/ResFilters.h
10  *
11 */
12 #ifndef ZYPP_RESFILTERS_H
13 #define ZYPP_RESFILTERS_H
14
15 #include <iosfwd>
16
17 #include "zypp/Resolvable.h"
18
19 ///////////////////////////////////////////////////////////////////
20 namespace zypp
21 { /////////////////////////////////////////////////////////////////
22   ///////////////////////////////////////////////////////////////////
23   namespace resfilter
24   { /////////////////////////////////////////////////////////////////
25     /** \defgroup RESFILTERS Filter functors operating on Resolvables.
26      *
27      * A simple filter is a function or functor matching the signature:
28      * \code
29      *   bool simplefilter( Resolvable::Ptr );
30      * \endcode
31      *
32      * \note It's not neccessary that your function or functor actually
33      * returns \c bool. Anything which is convertible into a \c bool
34      * will do;
35      *
36      * Besides basic filter functors which actually evaluate the
37      * \c Resolvable (e.g. \ref ByKind, \ref ByName), there are some
38      * special functors to build more complex queries:
39      *
40      * \li \ref True and \ref False. No supprise, they always return
41      *     \c true or \c false.
42      * \li \ref Not\<_Condition\>. _Condition is a filter functor, and
43      *     it's result is inverted.
44      * \li \ref Chain\<_ACondition,_BCondition\>. \c _ACondition and \c _BCondition
45      *     are filter functors, and Chain evaluates
46      *     <tt>_ACondition && _BCondition</tt>
47      *
48      * As it's no fun to get and write the correct template arguments,
49      * convenience functions creating the correct functor are provided.
50      *
51      * \li \c true_c and \c false_c. (provided just to match the schema)
52      * \li \c not_c. Takes a functor as argument and returns the appropriate
53      *     \ref Not functor.
54      * \li \c chain. Takes two functors and returns the appropriate
55      *     \ref Cain functor.
56      *
57      * \code
58      * // some 'action' functor, printing and counting
59      * // Resolvables.
60      * struct PrintAndCount
61      * {
62      *   PrintAndCount( unsigned & counter_r )
63      *   : _counter( counter_r )
64      *   {}
65      *
66      *   bool operator()( Resolvable::Ptr p ) const
67      *   {
68      *     DBG << *p << endl;
69      *     ++_counter;
70      *     return true;
71      *   }
72      *
73      *   unsigned & _counter;
74      * };
75      *
76      *
77      * ResStore store;
78      * unsigned counter = 0;
79      *
80      * // print and count all resolvables
81      * store.forEach( PrintAndCount(counter) );
82      *
83      * // print and count all resolvables named "kernel"
84      * counter = 0;
85      * store.forEach( ByName("kernel"), PrintAndCount(counter) );
86      *
87      * // print and count all Packages named "kernel"
88      * counter = 0;
89      * store.forEach( chain( ByKind(ResTraits<Package>::kind),
90      *                       ByName("kernel") ),
91      *                PrintAndCount(counter) );
92      *
93      * // print and count all Packages not named "kernel"
94      * counter = 0;
95      * store.forEach( chain( ByKind(ResTraits<Package>::kind),
96      *                       not_c(ByName("kernel")) ),
97      *                PrintAndCount(counter) );
98      *
99      * // same as above ;)
100      * counter = 0;
101      * store.forEach( chain( ByKind(ResTraits<Package>::kind),
102      *                       chain( not_c(ByName("kernel")),
103      *                              PrintAndCount(counter) ) ),
104      *                true_c() );
105      * \endcode
106      *
107      * As you can see in the last example there is no difference in using
108      * a filter or an action functor, as both have the same signature.
109      * A difference of course is the way forEach interprets the returned
110      * value.
111      *
112      * Consequently you can netgate and chain actions as well. Thus
113      * <tt>PrintAndCount(counter)</tt> could be
114      * <tt>chain(Print(),Count(counter))</tt>, if these functors are
115      * provided.
116      *
117      * \note These functors are not limited to be used with ResStore::forEach.
118      * You can use them with std::algorithms as well.
119      *
120      * \note In case you already have functions or methods which do what you
121      * want, but thet don't perfectly match the required signature: Make yourself
122      * familiar with <tt>std::ptr_fun, mem_fun, bind1st, bind2nd and compose</tt>.
123      * They are sometimes quite helpfull.
124      *
125      * \c PrintAndCount is an example how a functor can return data collected
126      * during the query. You ca easily write a collector, that takes a
127      * <tt>std:list\<Resolvable::Ptr\>\&</tt> and fills it with the matches
128      * found.
129      *
130      * But as a rule of thumb, a functor should be lightweight. If you
131      * want to get data out, pass references to variables in (and assert
132      * these variables live as long as the quiery lasts).
133      *
134      * Internally all functors are passed by value. Thus it would not help
135      * you to create an instance of some collecting functor, and pass it
136      * to the query. The query will then fill a copy of your functor, you
137      * won't get the data back. (Well, you probabely could, by using
138      * boosr::ref).
139      *
140      * Why functors and not plain functions?
141      *
142      * You can use plain functions if they don't have to deliver data back to
143      * the application.
144      * The \c C-style approach is having functions that take a <tt>void * data</tt>
145      * as last argument. This \c data pointer is then passed arround and casted
146      * up and down.
147      *
148      * If you look at a functor, you'll see that it contains both, the function
149      * to call (it's <tt>operator()</tt> ) and the data you'd otherwise pass as
150      * <tt>void * data</tt>. That's nice and safe.
151     */
152     //@{
153     ///////////////////////////////////////////////////////////////////
154     //
155     // Predefined filters
156     //
157     ///////////////////////////////////////////////////////////////////
158
159     struct True
160     {
161       bool operator()( Resolvable::Ptr ) const
162       {
163         return true;
164       }
165     };
166
167     True true_c()
168     { return True(); }
169
170     ///////////////////////////////////////////////////////////////////
171
172     struct False
173     {
174       bool operator()( Resolvable::Ptr ) const
175       {
176         return false;
177       }
178     };
179
180     False false_c()
181     { return False(); }
182
183     ///////////////////////////////////////////////////////////////////
184
185     template<class _Condition>
186       struct Not
187       {
188         Not( _Condition cond_r )
189         : _cond( cond_r )
190         {}
191         bool operator()( Resolvable::Ptr p ) const
192         {
193           return ! _cond( p );
194         }
195         _Condition _cond;
196       };
197
198     template<class _Condition>
199       Not<_Condition> not_c( _Condition cond_r )
200       {
201         return Not<_Condition>( cond_r );
202       }
203
204     ///////////////////////////////////////////////////////////////////
205
206     template<class _ACondition, class _BCondition>
207       struct Chain
208       {
209         Chain( _ACondition conda_r, _BCondition condb_r )
210         : _conda( conda_r )
211         , _condb( condb_r )
212         {}
213         bool operator()( Resolvable::Ptr p ) const
214         {
215           return _conda( p ) && _condb( p );
216         }
217         _ACondition _conda;
218         _BCondition _condb;
219       };
220
221     template<class _ACondition, class _BCondition>
222       Chain<_ACondition, _BCondition> chain( _ACondition conda_r, _BCondition condb_r )
223       {
224         return Chain<_ACondition, _BCondition>( conda_r, condb_r );
225       }
226
227     ///////////////////////////////////////////////////////////////////
228     //
229     // Now some Resolvable attributes
230     //
231     ///////////////////////////////////////////////////////////////////
232
233     struct ByKind
234     {
235       ByKind( const Resolvable::Kind & kind_r )
236       : _kind( kind_r )
237       {}
238       bool operator()( Resolvable::Ptr p ) const
239       {
240         return p->kind() == _kind;
241       }
242       Resolvable::Kind _kind;
243     };
244
245     struct ByName
246     {
247       ByName( const std::string & name_r )
248       : _name( name_r )
249       {}
250       bool operator()( Resolvable::Ptr p ) const
251       {
252         return p->name() == _name;
253       }
254       std::string _name;
255     };
256
257     ///////////////////////////////////////////////////////////////////
258
259     //@}
260     /////////////////////////////////////////////////////////////////
261   } // namespace resfilter
262   ///////////////////////////////////////////////////////////////////
263   /////////////////////////////////////////////////////////////////
264 } // namespace zypp
265 ///////////////////////////////////////////////////////////////////
266 #endif // ZYPP_RESFILTERS_H