1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/LookupAttr.h
12 #ifndef ZYPP_SAT_LOOKUPATTR_H
13 #define ZYPP_SAT_LOOKUPATTR_H
17 #include "zypp/base/PtrTypes.h"
18 #include "zypp/base/DefaultIntegral.h"
20 #include "zypp/sat/detail/PoolMember.h"
21 #include "zypp/sat/SolvAttr.h"
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
34 { /////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////
38 // CLASS NAME : LookupAttr
40 /** Lightweight attribute value lookup.
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.
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).
51 * For convenience \see \ref LookupRepoAttr.
53 * Modifying the query will not affect any running
56 * Use \ref SolvAttr::allAttr to search all attributes.
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.
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 );
75 * // look for all attributes of one solvable
76 * void ditest( sat::Solvable slv_r )
78 * sat::LookupAttr q( sat::SolvAttr::allAttr, slv_r );
79 * MIL << q << ": " << endl;
80 * for_( it, q.begin(), q.end() )
82 * MIL << " " << it.inSolvAttr() << " = " << it.asString() << endl;
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() )
93 * MIL << " " << it << endl;
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() )
103 * MIL << " " << it << endl;
110 typedef MatchException Exception;
113 typedef unsigned size_type;
115 /** Specify the where to look for the attribule. */
117 SOLV_ATTR = 0, //!< Search for solvable attributes (default)
118 REPO_ATTR = -1 //!< Search for repository attributes
122 /** Default ctor finds nothing. */
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 );
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 );
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 );
141 /** \name Search result. */
143 /** Result iterator. */
146 /** Iterator to the begin of query results. */
147 iterator begin() const;
149 /** Iterator behind the end of query results. */
150 iterator end() const;
152 /** Whether the query is empty. */
155 /** Ammount of results.
156 * \note This is not a cheap call. It runs the query.
158 size_type size() const;
160 /** TransformIterator returning an \ref iterator vaue of type \c TResult. */
161 template<class TResult, class TAttr = TResult>
162 class TransformIterator;
166 /** \name What to search. */
168 /** The \ref SolvAttr to search. */
169 SolvAttr attr() const;
171 /** Set the \ref SolvAttr to search. */
172 void setAttr( SolvAttr attr_r );
175 /** \name Restrict attributes to match a pattern. */
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:
182 * if ( q.strMatcher() )
183 * ...; // an StrMatcher is set
186 const StrMatcher & strMatcher() const;
188 /** Set the pattern to match.
189 * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
191 void setStrMatcher( const StrMatcher & matcher_r );
193 /** Reset the pattern to match. */
194 void resetStrMatcher();
198 /** \name Where to search. */
200 /** Whether to search in \ref Pool. */
203 /** Set search in \ref Pool (all repositories). */
204 void setPool( Location = SOLV_ATTR );
206 /** Whether to search in one \ref Repository. */
207 Repository repo() const;
209 /** Set search in one \ref Repository. */
210 void setRepo( Repository repo_r, Location = SOLV_ATTR );
212 /** Whether to search in one \ref Solvable. */
213 Solvable solvable() const;
215 /** Set search in one \ref Solvable. */
216 void setSolvable( Solvable solv_r );
218 /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
219 SolvAttr parent() const;
221 /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
222 void setParent( SolvAttr attr_r );
227 RWCOW_pointer<Impl> _pimpl;
229 ///////////////////////////////////////////////////////////////////
231 /** \relates LookupAttr Stream output. */
232 std::ostream & operator<<( std::ostream & str, const LookupAttr & obj );
234 /** \relates LookupAttr Verbose stream output including the query result. */
235 std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj );
237 ///////////////////////////////////////////////////////////////////
239 // CLASS NAME : LookupRepoAttr
241 /** Lightweight repository attribute value lookup.
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.
248 * // look for a repo attribute in the pool:
249 * sat::LookupAttr p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR );
251 * // Equivalent but using LookupRepoAttr:
252 * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
255 * \see \ref LookupAttr
257 class LookupRepoAttr : public LookupAttr
260 /** \copydoc LookupAttr::LookupAttr() */
263 /** \copydoc LookupAttr::LookupAttr(SolvAttr) */
264 explicit LookupRepoAttr( SolvAttr attr_r )
265 : LookupAttr( attr_r, REPO_ATTR )
267 /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */
268 explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r );
271 /** \copydoc LookupAttr::setPool */
273 { LookupAttr::setPool( REPO_ATTR ); }
274 /** \copydoc LookupAttr::setRepo */
275 void setRepo( Repository repo_r );
277 // Hide. You can't look inside and outside Solvables at the same time.
278 using LookupAttr::solvable;
279 using LookupAttr::setSolvable;
281 ///////////////////////////////////////////////////////////////////
285 /** Wrapper around sat \c detail::CDataiterator.
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.
295 /** \c NULL \c detail::CDataiterator */
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 );
308 void swap( DIWrap & rhs )
310 if ( &rhs != this ) // prevent self assign!
312 std::swap( _dip, rhs._dip );
313 std::swap( _mstring, rhs._mstring );
316 DIWrap & operator=( const DIWrap & rhs )
318 if ( &rhs != this ) // prevent self assign!
319 DIWrap( rhs ).swap( *this );
323 { DIWrap().swap( *this ); }
325 /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
326 explicit operator bool() const
330 detail::CDataiterator * operator->() const { return _dip; }
331 detail::CDataiterator * get() const { return _dip; }
332 const std::string & getstr() const { return _mstring; }
335 detail::CDataiterator * _dip;
336 std::string _mstring;
338 /** \relates DIWrap Stream output. */
339 std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
342 ///////////////////////////////////////////////////////////////////
344 // CLASS NAME : LookupAttr::iterator
347 * Extended iterator methods valid only if not @end.
348 * \note Implementation: Keep iterator_adaptor base and _dip in sync!
350 class LookupAttr::iterator : public boost::iterator_adaptor<
352 , detail::CDataiterator * // Base
353 , detail::IdType // Value
354 , boost::forward_traversal_tag // CategoryOrTraversal
355 , detail::IdType // Reference
359 /** \name Moving fast forward. */
361 /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */
362 void nextSkipSolvAttr();
364 /** On the next call to \ref operator++ advance to the next \ref Solvable. */
365 void nextSkipSolvable();
367 /** On the next call to \ref operator++ advance to the next \ref Repository. */
370 /** Immediately advance to the next \ref SolvAttr. */
372 { nextSkipSolvAttr(); increment(); }
374 /** Immediately advance to the next \ref Solvable. */
376 { nextSkipSolvable(); increment(); }
378 /** Immediately advance to the next \ref Repository. */
380 { nextSkipRepo(); increment(); }
382 /** Stop after all matches in the current \ref Solvable are processed. */
383 void stayInThisSolvable();
385 /** Stop after all matches in the current \ref Repository are processed. */
386 void stayInThisRepo();
389 /** \name Current position info. */
391 /** The current \ref Repository. */
392 Repository inRepo() const;
394 /** The current \ref Solvable. */
395 Solvable inSolvable() const;
397 /** The current \ref SolvAttr. */
398 SolvAttr inSolvAttr() const;
400 /** Whether this points to the end of a query (Iterator is invalid). */
405 /** \name Test attribute value type. */
407 /** The current \ref SolvAttr type. */
408 detail::IdType solvAttrType() const;
410 /** Whether this is a numeric attribute (incl. boolean). */
411 bool solvAttrNumeric() const;
413 /** Whether this is a string attribute. */
414 bool solvAttrString() const;
416 /** Whether this string attribute is available as \ref IdString. */
417 bool solvAttrIdString() const;
419 /** Whether this is a CheckSum attribute.*/
420 bool solvAttrCheckSum() const;
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.
426 bool solvAttrSubEntry() const;
429 /** \name Iterate sub-structures.
431 * These are usable iff \ref solvAttrSubEntry is \c true.
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.
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() )
445 * // List all sub values
446 * for_( sub, res.subBegin(), res.subEnd() )
448 * cout << sub.asString() << endl;
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;
459 /** Whether the sub-structure is empty. */
460 bool subEmpty() const;
462 /** Ammount of attributes in the sub-structure.
463 * \note This is not a cheap call. It runs the query.
465 size_type subSize() const;
467 /** Iterator to the begin of a sub-structure.
468 * \see \ref solvAttrSubEntry
470 iterator subBegin() const;
471 /** Iterator behind the end of a sub-structure.
472 * \see \ref solvAttrSubEntry
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
479 iterator subFind( SolvAttr attr_r ) const;
480 /** \overload Extending the current attribute name with by \c ":attrname_r".
482 * This assumes a sub-structur \c "update:reference" has attributes
483 * like \c "update:reference:type", \c "update:reference:href".
485 * If an empty \c attrname_r is passed, \ref subBegin is returned.
487 iterator subFind( const C_Str & attrname_r ) const;
490 /** \name Retrieving attribute values. */
492 /** Conversion to numeric types. */
495 unsigned asUnsigned() const;
499 unsigned long long asUnsignedLL() const;
501 /** Conversion to string types. */
502 const char * c_str() const;
504 * If used with non-string types, this method tries to create
505 * some appropriate string representation.
507 std::string asString() const;
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.
514 IdString idStr() const;
515 /** \overload Directly returning the \c Id */
516 detail::IdType id() const
517 { return idStr().id(); }
519 /** As \ref CheckSum. */
520 CheckSum asCheckSum() const;
522 /** Templated return type.
523 * Per default assumes an Id based type, so try to construct
526 * Should be specialized for supported types above.
528 template<class Tp> Tp asType() const { return Tp(id()); }
531 ///////////////////////////////////////////////////////////////////
532 // internal stuff below
533 ///////////////////////////////////////////////////////////////////
537 iterator( const iterator & rhs );
539 iterator & operator=( const iterator & rhs );
545 * C-tor taking over ownership of the passed \c detail::CDataiterator
546 * and doing it's first iteration (::dataiterator_step)
548 iterator( detail::DIWrap & dip_r );
551 friend class boost::iterator_core_access;
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
556 return ( bool(base()) == bool(rhs.base()) )
557 && ( ! base() || dip_equal( *base(), *rhs.base() ) );
560 bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const;
562 detail::IdType dereference() const;
567 /** Expert backdoor. */
568 detail::CDataiterator * get() const
569 { return _dip.get(); }
573 ///////////////////////////////////////////////////////////////////
575 /** \relates LookupAttr::iterator Stream output. */
576 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj );
578 ///////////////////////////////////////////////////////////////////
580 /** \name Helpers and forward declarations from LookupAttrTools.h */
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;
591 template<class TResult, class TAttr>
595 /////////////////////////////////////////////////////////////////
597 ///////////////////////////////////////////////////////////////////
598 /////////////////////////////////////////////////////////////////
600 ///////////////////////////////////////////////////////////////////
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 );
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; }
609 #endif // ZYPP_SAT_LOOKUPATTR_H