f0e72dc56e67838770431c03e2165d97400779e7
[platform/upstream/libzypp.git] / zypp / sat / LookupAttr.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/LookupAttr.h
10  *
11 */
12 #ifndef ZYPP_SAT_LOOKUPATTR_H
13 #define ZYPP_SAT_LOOKUPATTR_H
14
15 #include <iosfwd>
16
17 #include "zypp/base/PtrTypes.h"
18 #include "zypp/base/DefaultIntegral.h"
19
20 #include "zypp/sat/detail/PoolMember.h"
21 #include "zypp/sat/SolvAttr.h"
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27   class CheckSum;
28   class Match;
29   class MatchException;
30   class StrMatcher;
31
32   ///////////////////////////////////////////////////////////////////
33   namespace sat
34   { /////////////////////////////////////////////////////////////////
35
36     ///////////////////////////////////////////////////////////////////
37     //
38     //  CLASS NAME : LookupAttr
39     //
40     /** Lightweight attribute value lookup.
41      *
42      * Search for an attribute in \ref Pool, one \ref Repository
43      * or one \ref Solvable. \ref LookupAttr builds the query,
44      * \ref LookupAttr::iterator iterates over the result.
45      *
46      * Per default \ref LookupAttr looks for attributes associated with
47      * a \ref Solvable. But you may also pass \ref REPO_ATTR as
48      * \ref Location argument, to lookup attributes associated with
49      * the \ref Repository (e.g. DeltaRpm information).
50      *
51      * For convenience \see \ref LookupRepoAttr.
52      *
53      * Modifying the query will not affect any running
54      * iterator.
55      *
56      * Use \ref SolvAttr::allAttr to search all attributes.
57      *
58      * To search for attributes located in a sub-structure (flexarray)
59      * you also have to pass the sub-structures attribute as parent.
60      * Passing \ref SolvAttr::allAttr a parent will lookup the attribute
61      * in \c any sub-structure. Few attributes are known to have a parent
62      * (\see \ref SolvAttr::parent). Setting those attributes will automatically
63      * initialize their parent value.
64      *
65      * \code
66      *    // Lookup all 'name' attributes:
67      *    sat::LookupAttr q( sat::SolvAttr::name );
68      *    // Lookup all 'name' attributes within a sub-structure 'data':
69      *    sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::data );
70      *    // Lookup all 'name' attributes within any sub-structure:
71      *    sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::allAttr );
72      * \endcode
73      *
74      * \code
75      *  // look for all attributes of one solvable
76      *  void ditest( sat::Solvable slv_r )
77      *  {
78      *    sat::LookupAttr q( sat::SolvAttr::allAttr, slv_r );
79      *    MIL << q << ": " << endl;
80      *    for_( it, q.begin(), q.end() )
81      *    {
82      *      MIL << "    " << it.inSolvAttr() << " = " << it.asString() << endl;
83      *    }
84      *  }
85      * \endcode
86      *
87      * \code
88      *  // look for an attribute in the pool.
89      *  sat::LookupAttr q( sat::SolvAttr("susetags:datadir") );
90      *  MIL << q << ": " << endl;
91      *  for_( it, q.begin(), q.end() )
92      *  {
93      *    MIL << "    " << it << endl;
94      *  }
95      * \endcode
96      *
97      * \code
98      *  // look for a repo attribute in the pool.
99      *  sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
100      *  MIL << q << ": " << endl;
101      *  for_( it, q.begin(), q.end() )
102      *  {
103      *    MIL << "    " << it << endl;
104      *  }
105      * \endcode
106      */
107     class LookupAttr
108     {
109       public:
110         typedef MatchException Exception;
111
112       public:
113         typedef unsigned size_type;
114
115         /** Specify the where to look for the attribule. */
116         enum Location {
117           SOLV_ATTR = 0,  //!< Search for solvable attributes (default)
118           REPO_ATTR = -1  //!< Search for repository attributes
119         };
120
121       public:
122         /** Default ctor finds nothing. */
123         LookupAttr();
124
125         /** Lookup \ref SolvAttr in \ref Pool (all repositories). */
126         explicit LookupAttr( SolvAttr attr_r, Location = SOLV_ATTR );
127         /** \overload SolvAttr within sub-structure \a parent_r. */
128         LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location = SOLV_ATTR );
129
130         /** Lookup \ref SolvAttr in one\ref Repository. */
131         LookupAttr( SolvAttr attr_r, Repository repo_r, Location = SOLV_ATTR );
132         /** \overload SolvAttr within sub-structure \a parent_r. */
133         LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location = SOLV_ATTR );
134
135         /** Lookup \ref SolvAttr in one \ref Solvable. */
136         LookupAttr( SolvAttr attr_r, Solvable solv_r );
137         /** \overload SolvAttr within sub-structure \a parent_r. */
138         LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r );
139
140       public:
141         /** \name Search result. */
142         //@{
143         /** Result iterator. */
144         class iterator;
145
146         /** Iterator to the begin of query results. */
147         iterator begin() const;
148
149         /** Iterator behind the end of query results. */
150         iterator end() const;
151
152         /** Whether the query is empty. */
153         bool empty() const;
154
155         /** Ammount of results.
156          * \note This is not a cheap call. It runs the query.
157         */
158         size_type size() const;
159
160         /** TransformIterator returning an \ref iterator vaue of type \c _ResultT. */
161         template<class _ResultT, class _AttrT = _ResultT> class transformIterator;
162         //@}
163
164       public:
165         /** \name What to search. */
166         //@{
167         /** The \ref SolvAttr to search. */
168         SolvAttr attr() const;
169
170         /** Set the \ref SolvAttr to search. */
171         void setAttr( SolvAttr attr_r );
172         //@}
173
174         /** \name Restrict attributes to match a pattern. */
175         //@{
176         /** The pattern to match.
177          * You can also evaluate \ref StrMatcher in a boolean context,
178          * in order to test whether an \ref StrMatcher is set:
179          * \code
180          *   LookupAttr q;
181          *   if ( q.strMatcher() )
182          *     ...; // an StrMatcher is set
183          * \endcode
184         */
185         const StrMatcher & strMatcher() const;
186
187         /** Set the pattern to match.
188          * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
189          */
190         void setStrMatcher( const StrMatcher & matcher_r );
191
192         /** Reset the pattern to match. */
193         void resetStrMatcher();
194        //@}
195
196       public:
197         /** \name Where to search. */
198         //@{
199         /** Whether to search in \ref Pool. */
200         bool pool() const;
201
202         /** Set search in \ref Pool (all repositories). */
203         void setPool( Location = SOLV_ATTR );
204
205         /** Whether to search in one \ref Repository. */
206         Repository repo() const;
207
208         /** Set search in one \ref Repository. */
209         void setRepo( Repository repo_r, Location = SOLV_ATTR );
210
211         /** Whether to search in one \ref Solvable. */
212         Solvable solvable() const;
213
214         /** Set search in one \ref Solvable. */
215         void setSolvable( Solvable solv_r );
216
217         /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
218         SolvAttr parent() const;
219
220         /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
221         void setParent( SolvAttr attr_r );
222         //@}
223
224       private:
225         class Impl;
226         RWCOW_pointer<Impl> _pimpl;
227     };
228     ///////////////////////////////////////////////////////////////////
229
230     /** \relates LookupAttr Stream output. */
231     std::ostream & operator<<( std::ostream & str, const LookupAttr & obj );
232
233     /** \relates LookupAttr Verbose stream output including the query result. */
234     std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj );
235
236     ///////////////////////////////////////////////////////////////////
237     //
238     //  CLASS NAME : LookupRepoAttr
239     //
240     /** Lightweight repository attribute value lookup.
241      *
242      * This is just a convenience class that overloads all
243      * \ref LookupAttr methods which take a \ref LookupAttr::Location
244      * argument and sets it to \ref REPO_ATTR.
245      *
246      * \code
247      * // look for a repo attribute in the pool:
248      * sat::LookupAttr     p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR );
249      *
250      * // Equivalent but using LookupRepoAttr:
251      * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
252      * \endcode
253      *
254      * \see \ref LookupAttr
255      */
256     class LookupRepoAttr : public LookupAttr
257     {
258       public:
259         /** \copydoc LookupAttr::LookupAttr() */
260         LookupRepoAttr()
261         {}
262         /** \copydoc LookupAttr::LookupAttr(SolvAttr) */
263         explicit LookupRepoAttr( SolvAttr attr_r )
264         : LookupAttr( attr_r, REPO_ATTR )
265         {}
266         /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */
267         explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r );
268
269       public:
270         /** \copydoc LookupAttr::setPool */
271         void setPool()
272         { LookupAttr::setPool( REPO_ATTR ); }
273         /** \copydoc LookupAttr::setRepo */
274         void setRepo( Repository repo_r );
275       private:
276         // Hide. You can't look inside and outside Solvables at the same time.
277         using LookupAttr::solvable;
278         using LookupAttr::setSolvable;
279     };
280     ///////////////////////////////////////////////////////////////////
281
282     namespace detail
283     {
284       /** Wrapper around sat \c detail::CDataiterator.
285        *
286        * Manages copy and assign, and release of allocated
287        * resources like datamatcher inside the dataiterator.
288        * Also maintains a copy of the matchstring in order to
289        * keep the char* passed to the dataiterator valid.
290        */
291       class DIWrap
292       {
293         public:
294           /** \c NULL \c detail::CDataiterator */
295           DIWrap()
296           : _dip( 0 )
297           {}
298           /** Initializes */
299           DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
300                   const std::string & mstring_r = std::string(), int flags_r = 0 );
301           /** \overload to catch \c NULL \a mstring_r. */
302           DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
303                   const char * mstring_r, int flags_r = 0 );
304           DIWrap( const DIWrap & rhs );
305           ~DIWrap();
306         public:
307           void swap( DIWrap & rhs )
308           {
309             if ( &rhs != this ) // prevent self assign!
310             {
311               std::swap( _dip, rhs._dip );
312               std::swap( _mstring, rhs._mstring );
313             }
314           }
315           DIWrap & operator=( const DIWrap & rhs )
316           {
317             if ( &rhs != this ) // prevent self assign!
318               DIWrap( rhs ).swap( *this );
319             return *this;
320           }
321           void reset()
322           { DIWrap().swap( *this ); }
323         public:
324           /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
325           explicit operator bool() const
326           { return _dip; }
327
328         public:
329           detail::CDataiterator * operator->() const  { return _dip; }
330           detail::CDataiterator * get()        const  { return _dip; }
331           const std::string & getstr()   const  { return _mstring; }
332
333         private:
334           detail::CDataiterator * _dip;
335           std::string _mstring;
336       };
337       /** \relates DIWrap Stream output. */
338       std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
339     }
340
341     ///////////////////////////////////////////////////////////////////
342     //
343     //  CLASS NAME : LookupAttr::iterator
344     //
345     /** Result iterator.
346      * Extended iterator methods valid only if not @end.
347      * \note Implementation: Keep iterator_adaptor base and _dip in sync!
348      */
349     class LookupAttr::iterator : public boost::iterator_adaptor<
350         iterator                       // Derived
351         , detail::CDataiterator *            // Base
352         , detail::IdType               // Value
353         , boost::forward_traversal_tag // CategoryOrTraversal
354         , detail::IdType               // Reference
355     >
356     {
357       public:
358         /** \name Moving fast forward. */
359         //@{
360         /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */
361         void nextSkipSolvAttr();
362
363         /** On the next call to \ref operator++ advance to the next \ref Solvable. */
364         void nextSkipSolvable();
365
366         /** On the next call to \ref operator++ advance to the next \ref Repository. */
367         void nextSkipRepo();
368
369         /** Immediately advance to the next \ref SolvAttr. */
370         void skipSolvAttr()
371         { nextSkipSolvAttr(); increment(); }
372
373         /** Immediately advance to the next \ref Solvable. */
374         void skipSolvable()
375         { nextSkipSolvable(); increment(); }
376
377         /** Immediately advance to the next \ref Repository. */
378         void skipRepo()
379         { nextSkipRepo(); increment(); }
380
381         /** Stop after all matches in the current \ref Solvable are processed. */
382         void stayInThisSolvable();
383
384         /** Stop after all matches in the current \ref Repository are processed. */
385         void stayInThisRepo();
386         //@}
387
388         /** \name Current position info. */
389         //@{
390         /** The current \ref Repository. */
391         Repository inRepo() const;
392
393         /** The current \ref Solvable. */
394         Solvable inSolvable() const;
395
396         /** The current \ref SolvAttr. */
397         SolvAttr inSolvAttr() const;
398
399         /** Whether this points to the end of a query (Iterator is invalid). */
400         bool atEnd() const
401         { return !_dip; }
402         //@}
403
404         /** \name Test attribute value type. */
405         //@{
406         /** The current \ref SolvAttr type. */
407         detail::IdType solvAttrType() const;
408
409         /** Whether this is a numeric attribute (incl. boolean). */
410         bool solvAttrNumeric() const;
411
412         /** Whether this is a string attribute. */
413         bool solvAttrString() const;
414
415         /** Whether this string attribute is available as \ref IdString. */
416         bool solvAttrIdString() const;
417
418         /** Whether this is a CheckSum attribute.*/
419         bool solvAttrCheckSum() const;
420
421         /** Whether this is the entry to a sub-structure (flexarray).
422          * This is the entry to a sequence of attributes. To
423          * acces them use \ref subBegin and  \ref subEnd.
424         */
425         bool solvAttrSubEntry() const;
426         //@}
427
428         /** \name Iterate sub-structures.
429          *
430          * These are usable iff \ref solvAttrSubEntry is \c true.
431          *
432          * \note Unfortunately the underlying libsolv dataiterator as returned
433          * by \ref subBegin and \ref subFind loses some context when being created.
434          * Thus it's not possible to invoke \ref subBegin and \ref subFind on an
435          * iterator that was previously returned by one of those methods. The result
436          * will be an \c end iterator. For the same reason it is not possible for an
437          * iterator to leave the sub-structure again.
438          *
439          * \code
440          * // Lookup all "update:reference" entries for a specific solvable
441          * sat::LookupAttr q( sat::SolvAttr::updateReference, p->satSolvable() );
442          * for_( res, q.begin(), q.end() )
443          * {
444          *   // List all sub values
445          *   for_( sub, res.subBegin(), res.subEnd() )
446          *   {
447          *     cout << sub.asString() << endl;
448          *   }
449          *
450          *   // Directly access c specific value:
451          *   sat::LookupAttr::iterator it( res.subFind( sat::SolvAttr::updateReferenceHref ) );
452          *   if ( it != res.subEnd() )
453          *     cout << it.asString() << endl;
454          * }
455          * \endcode
456          */
457         //@{
458         /** Whether the sub-structure is empty. */
459         bool subEmpty() const;
460
461         /** Ammount of attributes in the sub-structure.
462          * \note This is not a cheap call. It runs the query.
463         */
464         size_type subSize() const;
465
466         /** Iterator to the begin of a sub-structure.
467          * \see \ref solvAttrSubEntry
468         */
469         iterator subBegin() const;
470         /** Iterator behind the end of a sub-structure.
471          * \see \ref solvAttrSubEntry
472         */
473         iterator subEnd() const;
474          /** Iterator pointing to the first occurance of \ref SolvAttr \a attr_r in sub-structure.
475           * If \ref sat::SolvAttr::allAttr is passed, \ref subBegin is returned.
476           * \see \ref solvAttrSubEntry
477          */
478         iterator subFind( SolvAttr attr_r ) const;
479         /** \overload Extending the current attribute name with by \c ":attrname_r".
480          *
481          * This assumes a sub-structur \c "update:reference" has attributes
482          * like \c "update:reference:type", \c "update:reference:href".
483          *
484          * If an empty \c attrname_r is passed, \ref subBegin is returned.
485         */
486         iterator subFind( const C_Str & attrname_r ) const;
487         //@}
488
489         /** \name Retrieving attribute values. */
490         //@{
491         /** Conversion to numeric types. */
492         int asInt() const;
493         /** \overload */
494         unsigned asUnsigned() const;
495         /** \overload */
496         bool asBool() const;
497         /** \overload */
498         unsigned long long asUnsignedLL() const;
499
500         /** Conversion to string types. */
501         const char * c_str() const;
502         /** \overload
503          * If used with non-string types, this method tries to create
504          * some appropriate string representation.
505         */
506         std::string asString() const;
507
508         /** As \ref IdStr.
509          * This is only done for poolized string types. Large strings like
510          * summary or descriptions are not available via \ref IdStr, only
511          * via \ref c_str and \ref asString.
512          */
513         IdString idStr() const;
514         /** \overload Directly returning the \c Id */
515         detail::IdType id() const
516         { return idStr().id(); }
517
518         /** As \ref CheckSum. */
519         CheckSum asCheckSum() const;
520
521         /** Templated return type.
522          * Per default assumes an Id based type, so try to construct
523          * it from the Id.
524          *
525          * Should be specialized for supported types above.
526         */
527         template<class _Tp> _Tp asType() const { return _Tp(id()); }
528         //@}
529
530         ///////////////////////////////////////////////////////////////////
531         // internal stuff below
532         ///////////////////////////////////////////////////////////////////
533       public:
534         iterator();
535
536         iterator( const iterator & rhs );
537
538         iterator & operator=( const iterator & rhs );
539
540         ~iterator();
541
542       public:
543         /**
544          * C-tor taking over ownership of the passed \c detail::CDataiterator
545          * and doing it's first iteration (::dataiterator_step)
546          */
547         iterator( detail::DIWrap & dip_r );
548
549       private:
550         friend class boost::iterator_core_access;
551
552         template <class OtherDerived, class OtherIterator, class V, class C, class R, class D>
553         bool equal( const boost::iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> & rhs ) const
554         {
555           return ( bool(base()) == bool(rhs.base()) )
556               && ( ! base() || dip_equal( *base(), *rhs.base() ) );
557         }
558
559         bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const;
560
561         detail::IdType dereference() const;
562
563         void increment();
564
565       public:
566         /** Expert backdoor. */
567         detail::CDataiterator * get() const
568         { return _dip.get(); }
569       private:
570         detail::DIWrap _dip;
571     };
572     ///////////////////////////////////////////////////////////////////
573
574     /** \relates LookupAttr::iterator Stream output. */
575     std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj );
576
577     ///////////////////////////////////////////////////////////////////
578
579     /** \name Helpers and forward declarations from LookupAttrTools.h */
580     //@{
581     template<> inline int          LookupAttr::iterator::asType<int>()          const { return asInt(); }
582     template<> inline unsigned     LookupAttr::iterator::asType<unsigned>()     const { return asUnsigned(); }
583     template<> inline unsigned long long LookupAttr::iterator::asType<unsigned long long>()     const { return asUnsignedLL(); }
584     template<> inline bool         LookupAttr::iterator::asType<bool>()         const { return asBool(); }
585     template<> inline const char * LookupAttr::iterator::asType<const char *>() const { return c_str(); }
586     template<> inline std::string  LookupAttr::iterator::asType<std::string>()  const { return asString(); }
587     template<> inline IdString     LookupAttr::iterator::asType<IdString>()     const { return idStr(); }
588     template<>        CheckSum     LookupAttr::iterator::asType<CheckSum>()     const;
589
590     template<class _ResultT, class _AttrT>
591     class ArrayAttr;
592     //@}
593
594     /////////////////////////////////////////////////////////////////
595   } // namespace sat
596   ///////////////////////////////////////////////////////////////////
597   /////////////////////////////////////////////////////////////////
598 } // namespace zypp
599 ///////////////////////////////////////////////////////////////////
600
601 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
602 std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj );
603
604 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
605 inline std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator & obj )
606 { return str << &obj; }
607
608 #endif // ZYPP_SAT_LOOKUPATTR_H