Imported Upstream version 16.3.2
[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 TResult. */
161         template<class TResult, class TAttr = TResult>
162         class TransformIterator;
163         //@}
164
165       public:
166         /** \name What to search. */
167         //@{
168         /** The \ref SolvAttr to search. */
169         SolvAttr attr() const;
170
171         /** Set the \ref SolvAttr to search. */
172         void setAttr( SolvAttr attr_r );
173         //@}
174
175         /** \name Restrict attributes to match a pattern. */
176         //@{
177         /** The pattern to match.
178          * You can also evaluate \ref StrMatcher in a boolean context,
179          * in order to test whether an \ref StrMatcher is set:
180          * \code
181          *   LookupAttr q;
182          *   if ( q.strMatcher() )
183          *     ...; // an StrMatcher is set
184          * \endcode
185         */
186         const StrMatcher & strMatcher() const;
187
188         /** Set the pattern to match.
189          * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
190          */
191         void setStrMatcher( const StrMatcher & matcher_r );
192
193         /** Reset the pattern to match. */
194         void resetStrMatcher();
195        //@}
196
197       public:
198         /** \name Where to search. */
199         //@{
200         /** Whether to search in \ref Pool. */
201         bool pool() const;
202
203         /** Set search in \ref Pool (all repositories). */
204         void setPool( Location = SOLV_ATTR );
205
206         /** Whether to search in one \ref Repository. */
207         Repository repo() const;
208
209         /** Set search in one \ref Repository. */
210         void setRepo( Repository repo_r, Location = SOLV_ATTR );
211
212         /** Whether to search in one \ref Solvable. */
213         Solvable solvable() const;
214
215         /** Set search in one \ref Solvable. */
216         void setSolvable( Solvable solv_r );
217
218         /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
219         SolvAttr parent() const;
220
221         /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
222         void setParent( SolvAttr attr_r );
223         //@}
224
225       private:
226         class Impl;
227         RWCOW_pointer<Impl> _pimpl;
228     };
229     ///////////////////////////////////////////////////////////////////
230
231     /** \relates LookupAttr Stream output. */
232     std::ostream & operator<<( std::ostream & str, const LookupAttr & obj );
233
234     /** \relates LookupAttr Verbose stream output including the query result. */
235     std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj );
236
237     ///////////////////////////////////////////////////////////////////
238     //
239     //  CLASS NAME : LookupRepoAttr
240     //
241     /** Lightweight repository attribute value lookup.
242      *
243      * This is just a convenience class that overloads all
244      * \ref LookupAttr methods which take a \ref LookupAttr::Location
245      * argument and sets it to \ref REPO_ATTR.
246      *
247      * \code
248      * // look for a repo attribute in the pool:
249      * sat::LookupAttr     p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR );
250      *
251      * // Equivalent but using LookupRepoAttr:
252      * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
253      * \endcode
254      *
255      * \see \ref LookupAttr
256      */
257     class LookupRepoAttr : public LookupAttr
258     {
259       public:
260         /** \copydoc LookupAttr::LookupAttr() */
261         LookupRepoAttr()
262         {}
263         /** \copydoc LookupAttr::LookupAttr(SolvAttr) */
264         explicit LookupRepoAttr( SolvAttr attr_r )
265         : LookupAttr( attr_r, REPO_ATTR )
266         {}
267         /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */
268         explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r );
269
270       public:
271         /** \copydoc LookupAttr::setPool */
272         void setPool()
273         { LookupAttr::setPool( REPO_ATTR ); }
274         /** \copydoc LookupAttr::setRepo */
275         void setRepo( Repository repo_r );
276       private:
277         // Hide. You can't look inside and outside Solvables at the same time.
278         using LookupAttr::solvable;
279         using LookupAttr::setSolvable;
280     };
281     ///////////////////////////////////////////////////////////////////
282
283     namespace detail
284     {
285       /** Wrapper around sat \c detail::CDataiterator.
286        *
287        * Manages copy and assign, and release of allocated
288        * resources like datamatcher inside the dataiterator.
289        * Also maintains a copy of the matchstring in order to
290        * keep the char* passed to the dataiterator valid.
291        */
292       class DIWrap
293       {
294         public:
295           /** \c NULL \c detail::CDataiterator */
296           DIWrap()
297           : _dip( 0 )
298           {}
299           /** Initializes */
300           DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
301                   const std::string & mstring_r = std::string(), int flags_r = 0 );
302           /** \overload to catch \c NULL \a mstring_r. */
303           DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
304                   const char * mstring_r, int flags_r = 0 );
305           DIWrap( const DIWrap & rhs );
306           ~DIWrap();
307         public:
308           void swap( DIWrap & rhs )
309           {
310             if ( &rhs != this ) // prevent self assign!
311             {
312               std::swap( _dip, rhs._dip );
313               std::swap( _mstring, rhs._mstring );
314             }
315           }
316           DIWrap & operator=( const DIWrap & rhs )
317           {
318             if ( &rhs != this ) // prevent self assign!
319               DIWrap( rhs ).swap( *this );
320             return *this;
321           }
322           void reset()
323           { DIWrap().swap( *this ); }
324         public:
325           /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
326           explicit operator bool() const
327           { return _dip; }
328
329         public:
330           detail::CDataiterator * operator->() const  { return _dip; }
331           detail::CDataiterator * get()        const  { return _dip; }
332           const std::string & getstr()   const  { return _mstring; }
333
334         private:
335           detail::CDataiterator * _dip;
336           std::string _mstring;
337       };
338       /** \relates DIWrap Stream output. */
339       std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
340     }
341
342     ///////////////////////////////////////////////////////////////////
343     //
344     //  CLASS NAME : LookupAttr::iterator
345     //
346     /** Result iterator.
347      * Extended iterator methods valid only if not @end.
348      * \note Implementation: Keep iterator_adaptor base and _dip in sync!
349      */
350     class LookupAttr::iterator : public boost::iterator_adaptor<
351         iterator                       // Derived
352         , detail::CDataiterator *            // Base
353         , detail::IdType               // Value
354         , boost::forward_traversal_tag // CategoryOrTraversal
355         , detail::IdType               // Reference
356     >
357     {
358       public:
359         /** \name Moving fast forward. */
360         //@{
361         /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */
362         void nextSkipSolvAttr();
363
364         /** On the next call to \ref operator++ advance to the next \ref Solvable. */
365         void nextSkipSolvable();
366
367         /** On the next call to \ref operator++ advance to the next \ref Repository. */
368         void nextSkipRepo();
369
370         /** Immediately advance to the next \ref SolvAttr. */
371         void skipSolvAttr()
372         { nextSkipSolvAttr(); increment(); }
373
374         /** Immediately advance to the next \ref Solvable. */
375         void skipSolvable()
376         { nextSkipSolvable(); increment(); }
377
378         /** Immediately advance to the next \ref Repository. */
379         void skipRepo()
380         { nextSkipRepo(); increment(); }
381
382         /** Stop after all matches in the current \ref Solvable are processed. */
383         void stayInThisSolvable();
384
385         /** Stop after all matches in the current \ref Repository are processed. */
386         void stayInThisRepo();
387         //@}
388
389         /** \name Current position info. */
390         //@{
391         /** The current \ref Repository. */
392         Repository inRepo() const;
393
394         /** The current \ref Solvable. */
395         Solvable inSolvable() const;
396
397         /** The current \ref SolvAttr. */
398         SolvAttr inSolvAttr() const;
399
400         /** Whether this points to the end of a query (Iterator is invalid). */
401         bool atEnd() const
402         { return !_dip; }
403         //@}
404
405         /** \name Test attribute value type. */
406         //@{
407         /** The current \ref SolvAttr type. */
408         detail::IdType solvAttrType() const;
409
410         /** Whether this is a numeric attribute (incl. boolean). */
411         bool solvAttrNumeric() const;
412
413         /** Whether this is a string attribute. */
414         bool solvAttrString() const;
415
416         /** Whether this string attribute is available as \ref IdString. */
417         bool solvAttrIdString() const;
418
419         /** Whether this is a CheckSum attribute.*/
420         bool solvAttrCheckSum() const;
421
422         /** Whether this is the entry to a sub-structure (flexarray).
423          * This is the entry to a sequence of attributes. To
424          * acces them use \ref subBegin and  \ref subEnd.
425         */
426         bool solvAttrSubEntry() const;
427         //@}
428
429         /** \name Iterate sub-structures.
430          *
431          * These are usable iff \ref solvAttrSubEntry is \c true.
432          *
433          * \note Unfortunately the underlying libsolv dataiterator as returned
434          * by \ref subBegin and \ref subFind loses some context when being created.
435          * Thus it's not possible to invoke \ref subBegin and \ref subFind on an
436          * iterator that was previously returned by one of those methods. The result
437          * will be an \c end iterator. For the same reason it is not possible for an
438          * iterator to leave the sub-structure again.
439          *
440          * \code
441          * // Lookup all "update:reference" entries for a specific solvable
442          * sat::LookupAttr q( sat::SolvAttr::updateReference, p->satSolvable() );
443          * for_( res, q.begin(), q.end() )
444          * {
445          *   // List all sub values
446          *   for_( sub, res.subBegin(), res.subEnd() )
447          *   {
448          *     cout << sub.asString() << endl;
449          *   }
450          *
451          *   // Directly access c specific value:
452          *   sat::LookupAttr::iterator it( res.subFind( sat::SolvAttr::updateReferenceHref ) );
453          *   if ( it != res.subEnd() )
454          *     cout << it.asString() << endl;
455          * }
456          * \endcode
457          */
458         //@{
459         /** Whether the sub-structure is empty. */
460         bool subEmpty() const;
461
462         /** Ammount of attributes in the sub-structure.
463          * \note This is not a cheap call. It runs the query.
464         */
465         size_type subSize() const;
466
467         /** Iterator to the begin of a sub-structure.
468          * \see \ref solvAttrSubEntry
469         */
470         iterator subBegin() const;
471         /** Iterator behind the end of a sub-structure.
472          * \see \ref solvAttrSubEntry
473         */
474         iterator subEnd() const;
475          /** Iterator pointing to the first occurance of \ref SolvAttr \a attr_r in sub-structure.
476           * If \ref sat::SolvAttr::allAttr is passed, \ref subBegin is returned.
477           * \see \ref solvAttrSubEntry
478          */
479         iterator subFind( SolvAttr attr_r ) const;
480         /** \overload Extending the current attribute name with by \c ":attrname_r".
481          *
482          * This assumes a sub-structur \c "update:reference" has attributes
483          * like \c "update:reference:type", \c "update:reference:href".
484          *
485          * If an empty \c attrname_r is passed, \ref subBegin is returned.
486         */
487         iterator subFind( const C_Str & attrname_r ) const;
488         //@}
489
490         /** \name Retrieving attribute values. */
491         //@{
492         /** Conversion to numeric types. */
493         int asInt() const;
494         /** \overload */
495         unsigned asUnsigned() const;
496         /** \overload */
497         bool asBool() const;
498         /** \overload */
499         unsigned long long asUnsignedLL() const;
500
501         /** Conversion to string types. */
502         const char * c_str() const;
503         /** \overload
504          * If used with non-string types, this method tries to create
505          * some appropriate string representation.
506         */
507         std::string asString() const;
508
509         /** As \ref IdStr.
510          * This is only done for poolized string types. Large strings like
511          * summary or descriptions are not available via \ref IdStr, only
512          * via \ref c_str and \ref asString.
513          */
514         IdString idStr() const;
515         /** \overload Directly returning the \c Id */
516         detail::IdType id() const
517         { return idStr().id(); }
518
519         /** As \ref CheckSum. */
520         CheckSum asCheckSum() const;
521
522         /** Templated return type.
523          * Per default assumes an Id based type, so try to construct
524          * it from the Id.
525          *
526          * Should be specialized for supported types above.
527         */
528         template<class Tp> Tp asType() const { return Tp(id()); }
529         //@}
530
531         ///////////////////////////////////////////////////////////////////
532         // internal stuff below
533         ///////////////////////////////////////////////////////////////////
534       public:
535         iterator();
536
537         iterator( const iterator & rhs );
538
539         iterator & operator=( const iterator & rhs );
540
541         ~iterator();
542
543       public:
544         /**
545          * C-tor taking over ownership of the passed \c detail::CDataiterator
546          * and doing it's first iteration (::dataiterator_step)
547          */
548         iterator( detail::DIWrap & dip_r );
549
550       private:
551         friend class boost::iterator_core_access;
552
553         template <class OtherDerived, class OtherIterator, class V, class C, class R, class D>
554         bool equal( const boost::iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> & rhs ) const
555         {
556           return ( bool(base()) == bool(rhs.base()) )
557               && ( ! base() || dip_equal( *base(), *rhs.base() ) );
558         }
559
560         bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const;
561
562         detail::IdType dereference() const;
563
564         void increment();
565
566       public:
567         /** Expert backdoor. */
568         detail::CDataiterator * get() const
569         { return _dip.get(); }
570       private:
571         detail::DIWrap _dip;
572     };
573     ///////////////////////////////////////////////////////////////////
574
575     /** \relates LookupAttr::iterator Stream output. */
576     std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj );
577
578     ///////////////////////////////////////////////////////////////////
579
580     /** \name Helpers and forward declarations from LookupAttrTools.h */
581     //@{
582     template<> inline int          LookupAttr::iterator::asType<int>()          const { return asInt(); }
583     template<> inline unsigned     LookupAttr::iterator::asType<unsigned>()     const { return asUnsigned(); }
584     template<> inline unsigned long long LookupAttr::iterator::asType<unsigned long long>()     const { return asUnsignedLL(); }
585     template<> inline bool         LookupAttr::iterator::asType<bool>()         const { return asBool(); }
586     template<> inline const char * LookupAttr::iterator::asType<const char *>() const { return c_str(); }
587     template<> inline std::string  LookupAttr::iterator::asType<std::string>()  const { return asString(); }
588     template<> inline IdString     LookupAttr::iterator::asType<IdString>()     const { return idStr(); }
589     template<>        CheckSum     LookupAttr::iterator::asType<CheckSum>()     const;
590
591     template<class TResult, class TAttr>
592     class ArrayAttr;
593     //@}
594
595     /////////////////////////////////////////////////////////////////
596   } // namespace sat
597   ///////////////////////////////////////////////////////////////////
598   /////////////////////////////////////////////////////////////////
599 } // namespace zypp
600 ///////////////////////////////////////////////////////////////////
601
602 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
603 std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj );
604
605 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
606 inline std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator & obj )
607 { return str << &obj; }
608
609 #endif // ZYPP_SAT_LOOKUPATTR_H