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