1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/LookupAttr.h
12 #ifndef ZYPP_SAT_LOOKUPATTR_H
13 #define ZYPP_SAT_LOOKUPATTR_H
21 #include "zypp/base/PtrTypes.h"
22 #include "zypp/base/DefaultIntegral.h"
24 #include "zypp/sat/detail/PoolMember.h"
25 #include "zypp/sat/SolvAttr.h"
27 ///////////////////////////////////////////////////////////////////
29 { /////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////
38 { /////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////
42 // CLASS NAME : LookupAttr
44 /** Lightweight attribute value lookup.
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.
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).
55 * For convenience \see \ref LookupRepoAttr.
57 * Modifying the query will not affect any running
60 * Use \ref SolvAttr::allAttr to search all attributes.
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.
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 );
79 * // look for all attributes of one solvable
80 * void ditest( sat::Solvable slv_r )
82 * sat::LookupAttr q( sat::SolvAttr::allAttr, slv_r );
83 * MIL << q << ": " << endl;
84 * for_( it, q.begin(), q.end() )
86 * MIL << " " << it.inSolvAttr() << " = " << it.asString() << endl;
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() )
97 * MIL << " " << it << endl;
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() )
107 * MIL << " " << it << endl;
114 typedef MatchException Exception;
117 typedef unsigned size_type;
119 /** Specify the where to look for the attribule. */
121 SOLV_ATTR = 0, //!< Search for solvable attributes (default)
122 REPO_ATTR = -1 //!< Search for repository attributes
126 /** Default ctor finds nothing. */
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 );
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 );
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 );
145 /** \name Search result. */
147 /** Result iterator. */
150 /** Iterator to the begin of query results. */
151 iterator begin() const;
153 /** Iterator behind the end of query results. */
154 iterator end() const;
156 /** Whether the query is empty. */
159 /** Ammount of results.
160 * \note This is not a cheap call. It runs the query.
162 size_type size() const;
164 /** TransformIterator returning an \ref iterator vaue of type \c _ResultT. */
165 template<class _ResultT, class _AttrT = _ResultT> class transformIterator;
169 /** \name What to search. */
171 /** The \ref SolvAttr to search. */
172 SolvAttr attr() const;
174 /** Set the \ref SolvAttr to search. */
175 void setAttr( SolvAttr attr_r );
178 /** \name Restrict attributes to match a pattern. */
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:
185 * if ( q.strMatcher() )
186 * ...; // an StrMatcher is set
189 const StrMatcher & strMatcher() const;
191 /** Set the pattern to match.
192 * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
194 void setStrMatcher( const StrMatcher & matcher_r );
196 /** Reset the pattern to match. */
197 void resetStrMatcher();
201 /** \name Where to search. */
203 /** Whether to search in \ref Pool. */
206 /** Set search in \ref Pool (all repositories). */
207 void setPool( Location = SOLV_ATTR );
209 /** Whether to search in one \ref Repository. */
210 Repository repo() const;
212 /** Set search in one \ref Repository. */
213 void setRepo( Repository repo_r, Location = SOLV_ATTR );
215 /** Whether to search in one \ref Solvable. */
216 Solvable solvable() const;
218 /** Set search in one \ref Solvable. */
219 void setSolvable( Solvable solv_r );
221 /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
222 SolvAttr parent() const;
224 /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
225 void setParent( SolvAttr attr_r );
230 RWCOW_pointer<Impl> _pimpl;
232 ///////////////////////////////////////////////////////////////////
234 /** \relates LookupAttr Stream output. */
235 std::ostream & operator<<( std::ostream & str, const LookupAttr & obj );
237 /** \relates LookupAttr Verbose stream output including the query result. */
238 std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj );
240 ///////////////////////////////////////////////////////////////////
242 // CLASS NAME : LookupRepoAttr
244 /** Lightweight repository attribute value lookup.
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.
251 * // look for a repo attribute in the pool:
252 * sat::LookupAttr p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR );
254 * // Equivalent but using LookupRepoAttr:
255 * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
258 * \see \ref LookupAttr
260 class LookupRepoAttr : public LookupAttr
263 /** \copydoc LookupAttr::LookupAttr() */
266 /** \copydoc LookupAttr::LookupAttr(SolvAttr) */
267 explicit LookupRepoAttr( SolvAttr attr_r )
268 : LookupAttr( attr_r, REPO_ATTR )
270 /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */
271 explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r );
274 /** \copydoc LookupAttr::setPool */
276 { LookupAttr::setPool( REPO_ATTR ); }
277 /** \copydoc LookupAttr::setRepo */
278 void setRepo( Repository repo_r );
280 // Hide. You can't look inside and outside Solvables at the same time.
281 using LookupAttr::solvable;
282 using LookupAttr::setSolvable;
284 ///////////////////////////////////////////////////////////////////
288 /** Wrapper around sat \c ::_Dataiterator.
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.
298 /** \c NULL \c ::_Dataiterator */
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 );
311 void swap( DIWrap & rhs )
313 if ( &rhs != this ) // prevent self assign!
315 std::swap( _dip, rhs._dip );
316 std::swap( _mstring, rhs._mstring );
319 DIWrap & operator=( const DIWrap & rhs )
321 if ( &rhs != this ) // prevent self assign!
322 DIWrap( rhs ).swap( *this );
326 { DIWrap().swap( *this ); }
328 /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
329 explicit operator bool() const
333 ::_Dataiterator * operator->() const { return _dip; }
334 ::_Dataiterator * get() const { return _dip; }
335 const std::string & getstr() const { return _mstring; }
338 ::_Dataiterator * _dip;
339 std::string _mstring;
341 /** \relates DIWrap Stream output. */
342 std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
345 ///////////////////////////////////////////////////////////////////
347 // CLASS NAME : LookupAttr::iterator
350 * Extended iterator methods valid only if not @end.
351 * \note Implementation: Keep iterator_adaptor base and _dip in sync!
353 class LookupAttr::iterator : public boost::iterator_adaptor<
355 , ::_Dataiterator * // Base
356 , detail::IdType // Value
357 , boost::forward_traversal_tag // CategoryOrTraversal
358 , detail::IdType // Reference
362 /** \name Moving fast forward. */
364 /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */
365 void nextSkipSolvAttr();
367 /** On the next call to \ref operator++ advance to the next \ref Solvable. */
368 void nextSkipSolvable();
370 /** On the next call to \ref operator++ advance to the next \ref Repository. */
373 /** Immediately advance to the next \ref SolvAttr. */
375 { nextSkipSolvAttr(); increment(); }
377 /** Immediately advance to the next \ref Solvable. */
379 { nextSkipSolvable(); increment(); }
381 /** Immediately advance to the next \ref Repository. */
383 { nextSkipRepo(); increment(); }
385 /** Stop after all matches in the current \ref Solvable are processed. */
386 void stayInThisSolvable();
388 /** Stop after all matches in the current \ref Repository are processed. */
389 void stayInThisRepo();
392 /** \name Current position info. */
394 /** The current \ref Repository. */
395 Repository inRepo() const;
397 /** The current \ref Solvable. */
398 Solvable inSolvable() const;
400 /** The current \ref SolvAttr. */
401 SolvAttr inSolvAttr() const;
403 /** Whether this points to the end of a query (Iterator is invalid). */
408 /** \name Test attribute value type. */
410 /** The current \ref SolvAttr type. */
411 detail::IdType solvAttrType() const;
413 /** Whether this is a numeric attribute (incl. boolean). */
414 bool solvAttrNumeric() const;
416 /** Whether this is a string attribute. */
417 bool solvAttrString() const;
419 /** Whether this string attribute is available as \ref IdString. */
420 bool solvAttrIdString() const;
422 /** Whether this is a CheckSum attribute.*/
423 bool solvAttrCheckSum() const;
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.
429 bool solvAttrSubEntry() const;
432 /** \name Iterate sub-structures.
434 * These are usable iff \ref solvAttrSubEntry is \c true.
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.
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() )
448 * // List all sub values
449 * for_( sub, res.subBegin(), res.subEnd() )
451 * cout << sub.asString() << endl;
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;
462 /** Whether the sub-structure is empty. */
463 bool subEmpty() const;
465 /** Ammount of attributes in the sub-structure.
466 * \note This is not a cheap call. It runs the query.
468 size_type subSize() const;
470 /** Iterator to the begin of a sub-structure.
471 * \see \ref solvAttrSubEntry
473 iterator subBegin() const;
474 /** Iterator behind the end of a sub-structure.
475 * \see \ref solvAttrSubEntry
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
482 iterator subFind( SolvAttr attr_r ) const;
483 /** \overload Extending the current attribute name with by \c ":attrname_r".
485 * This assumes a sub-structur \c "update:reference" has attributes
486 * like \c "update:reference:type", \c "update:reference:href".
488 * If an empty \c attrname_r is passed, \ref subBegin is returned.
490 iterator subFind( const C_Str & attrname_r ) const;
493 /** \name Retrieving attribute values. */
495 /** Conversion to numeric types. */
498 unsigned asUnsigned() const;
502 unsigned long long asUnsignedLL() const;
504 /** Conversion to string types. */
505 const char * c_str() const;
507 * If used with non-string types, this method tries to create
508 * some appropriate string representation.
510 std::string asString() const;
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.
517 IdString idStr() const;
518 /** \overload Directly returning the \c Id */
519 detail::IdType id() const
520 { return idStr().id(); }
522 /** As \ref CheckSum. */
523 CheckSum asCheckSum() const;
525 /** Templated return type.
526 * Per default assumes an Id based type, so try to construct
529 * Should be specialized for supported types above.
531 template<class _Tp> _Tp asType() const { return _Tp(id()); }
534 ///////////////////////////////////////////////////////////////////
535 // internal stuff below
536 ///////////////////////////////////////////////////////////////////
540 iterator( const iterator & rhs );
542 iterator & operator=( const iterator & rhs );
548 * C-tor taking over ownership of the passed \c ::_Dataiterator
549 * and doing it's first iteration (::dataiterator_step)
551 iterator( detail::DIWrap & dip_r );
554 friend class boost::iterator_core_access;
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
559 return ( bool(base()) == bool(rhs.base()) )
560 && ( ! base() || dip_equal( *base(), *rhs.base() ) );
563 bool dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const;
565 detail::IdType dereference() const;
570 /** Expert backdoor. */
571 ::_Dataiterator * get() const
572 { return _dip.get(); }
576 ///////////////////////////////////////////////////////////////////
578 /** \relates LookupAttr::iterator Stream output. */
579 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj );
581 ///////////////////////////////////////////////////////////////////
583 /** \name Helpers and forward declarations from LookupAttrTools.h */
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;
594 template<class _ResultT, class _AttrT>
598 /////////////////////////////////////////////////////////////////
600 ///////////////////////////////////////////////////////////////////
601 /////////////////////////////////////////////////////////////////
603 ///////////////////////////////////////////////////////////////////
605 /** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */
606 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj );
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; }
612 #endif // ZYPP_SAT_LOOKUPATTR_H