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 _ResultT. */
161 template<class _ResultT, class _AttrT = _ResultT> class transformIterator;
165 /** \name What to search. */
167 /** The \ref SolvAttr to search. */
168 SolvAttr attr() const;
170 /** Set the \ref SolvAttr to search. */
171 void setAttr( SolvAttr attr_r );
174 /** \name Restrict attributes to match a pattern. */
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:
181 * if ( q.strMatcher() )
182 * ...; // an StrMatcher is set
185 const StrMatcher & strMatcher() const;
187 /** Set the pattern to match.
188 * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile.
190 void setStrMatcher( const StrMatcher & matcher_r );
192 /** Reset the pattern to match. */
193 void resetStrMatcher();
197 /** \name Where to search. */
199 /** Whether to search in \ref Pool. */
202 /** Set search in \ref Pool (all repositories). */
203 void setPool( Location = SOLV_ATTR );
205 /** Whether to search in one \ref Repository. */
206 Repository repo() const;
208 /** Set search in one \ref Repository. */
209 void setRepo( Repository repo_r, Location = SOLV_ATTR );
211 /** Whether to search in one \ref Solvable. */
212 Solvable solvable() const;
214 /** Set search in one \ref Solvable. */
215 void setSolvable( Solvable solv_r );
217 /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */
218 SolvAttr parent() const;
220 /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */
221 void setParent( SolvAttr attr_r );
226 RWCOW_pointer<Impl> _pimpl;
228 ///////////////////////////////////////////////////////////////////
230 /** \relates LookupAttr Stream output. */
231 std::ostream & operator<<( std::ostream & str, const LookupAttr & obj );
233 /** \relates LookupAttr Verbose stream output including the query result. */
234 std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj );
236 ///////////////////////////////////////////////////////////////////
238 // CLASS NAME : LookupRepoAttr
240 /** Lightweight repository attribute value lookup.
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.
247 * // look for a repo attribute in the pool:
248 * sat::LookupAttr p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR );
250 * // Equivalent but using LookupRepoAttr:
251 * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides );
254 * \see \ref LookupAttr
256 class LookupRepoAttr : public LookupAttr
259 /** \copydoc LookupAttr::LookupAttr() */
262 /** \copydoc LookupAttr::LookupAttr(SolvAttr) */
263 explicit LookupRepoAttr( SolvAttr attr_r )
264 : LookupAttr( attr_r, REPO_ATTR )
266 /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */
267 explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r );
270 /** \copydoc LookupAttr::setPool */
272 { LookupAttr::setPool( REPO_ATTR ); }
273 /** \copydoc LookupAttr::setRepo */
274 void setRepo( Repository repo_r );
276 // Hide. You can't look inside and outside Solvables at the same time.
277 using LookupAttr::solvable;
278 using LookupAttr::setSolvable;
280 ///////////////////////////////////////////////////////////////////
284 /** Wrapper around sat \c detail::CDataiterator.
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.
294 /** \c NULL \c detail::CDataiterator */
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 );
307 void swap( DIWrap & rhs )
309 if ( &rhs != this ) // prevent self assign!
311 std::swap( _dip, rhs._dip );
312 std::swap( _mstring, rhs._mstring );
315 DIWrap & operator=( const DIWrap & rhs )
317 if ( &rhs != this ) // prevent self assign!
318 DIWrap( rhs ).swap( *this );
322 { DIWrap().swap( *this ); }
324 /** Evaluate in a boolean context <tt>( _dip != NULL )</tt>. */
325 explicit operator bool() const
329 detail::CDataiterator * operator->() const { return _dip; }
330 detail::CDataiterator * get() const { return _dip; }
331 const std::string & getstr() const { return _mstring; }
334 detail::CDataiterator * _dip;
335 std::string _mstring;
337 /** \relates DIWrap Stream output. */
338 std::ostream & operator<<( std::ostream & str, const DIWrap & obj );
341 ///////////////////////////////////////////////////////////////////
343 // CLASS NAME : LookupAttr::iterator
346 * Extended iterator methods valid only if not @end.
347 * \note Implementation: Keep iterator_adaptor base and _dip in sync!
349 class LookupAttr::iterator : public boost::iterator_adaptor<
351 , detail::CDataiterator * // Base
352 , detail::IdType // Value
353 , boost::forward_traversal_tag // CategoryOrTraversal
354 , detail::IdType // Reference
358 /** \name Moving fast forward. */
360 /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */
361 void nextSkipSolvAttr();
363 /** On the next call to \ref operator++ advance to the next \ref Solvable. */
364 void nextSkipSolvable();
366 /** On the next call to \ref operator++ advance to the next \ref Repository. */
369 /** Immediately advance to the next \ref SolvAttr. */
371 { nextSkipSolvAttr(); increment(); }
373 /** Immediately advance to the next \ref Solvable. */
375 { nextSkipSolvable(); increment(); }
377 /** Immediately advance to the next \ref Repository. */
379 { nextSkipRepo(); increment(); }
381 /** Stop after all matches in the current \ref Solvable are processed. */
382 void stayInThisSolvable();
384 /** Stop after all matches in the current \ref Repository are processed. */
385 void stayInThisRepo();
388 /** \name Current position info. */
390 /** The current \ref Repository. */
391 Repository inRepo() const;
393 /** The current \ref Solvable. */
394 Solvable inSolvable() const;
396 /** The current \ref SolvAttr. */
397 SolvAttr inSolvAttr() const;
399 /** Whether this points to the end of a query (Iterator is invalid). */
404 /** \name Test attribute value type. */
406 /** The current \ref SolvAttr type. */
407 detail::IdType solvAttrType() const;
409 /** Whether this is a numeric attribute (incl. boolean). */
410 bool solvAttrNumeric() const;
412 /** Whether this is a string attribute. */
413 bool solvAttrString() const;
415 /** Whether this string attribute is available as \ref IdString. */
416 bool solvAttrIdString() const;
418 /** Whether this is a CheckSum attribute.*/
419 bool solvAttrCheckSum() const;
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.
425 bool solvAttrSubEntry() const;
428 /** \name Iterate sub-structures.
430 * These are usable iff \ref solvAttrSubEntry is \c true.
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.
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() )
444 * // List all sub values
445 * for_( sub, res.subBegin(), res.subEnd() )
447 * cout << sub.asString() << endl;
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;
458 /** Whether the sub-structure is empty. */
459 bool subEmpty() const;
461 /** Ammount of attributes in the sub-structure.
462 * \note This is not a cheap call. It runs the query.
464 size_type subSize() const;
466 /** Iterator to the begin of a sub-structure.
467 * \see \ref solvAttrSubEntry
469 iterator subBegin() const;
470 /** Iterator behind the end of a sub-structure.
471 * \see \ref solvAttrSubEntry
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
478 iterator subFind( SolvAttr attr_r ) const;
479 /** \overload Extending the current attribute name with by \c ":attrname_r".
481 * This assumes a sub-structur \c "update:reference" has attributes
482 * like \c "update:reference:type", \c "update:reference:href".
484 * If an empty \c attrname_r is passed, \ref subBegin is returned.
486 iterator subFind( const C_Str & attrname_r ) const;
489 /** \name Retrieving attribute values. */
491 /** Conversion to numeric types. */
494 unsigned asUnsigned() const;
498 unsigned long long asUnsignedLL() const;
500 /** Conversion to string types. */
501 const char * c_str() const;
503 * If used with non-string types, this method tries to create
504 * some appropriate string representation.
506 std::string asString() const;
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.
513 IdString idStr() const;
514 /** \overload Directly returning the \c Id */
515 detail::IdType id() const
516 { return idStr().id(); }
518 /** As \ref CheckSum. */
519 CheckSum asCheckSum() const;
521 /** Templated return type.
522 * Per default assumes an Id based type, so try to construct
525 * Should be specialized for supported types above.
527 template<class _Tp> _Tp asType() const { return _Tp(id()); }
530 ///////////////////////////////////////////////////////////////////
531 // internal stuff below
532 ///////////////////////////////////////////////////////////////////
536 iterator( const iterator & rhs );
538 iterator & operator=( const iterator & rhs );
544 * C-tor taking over ownership of the passed \c detail::CDataiterator
545 * and doing it's first iteration (::dataiterator_step)
547 iterator( detail::DIWrap & dip_r );
550 friend class boost::iterator_core_access;
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
555 return ( bool(base()) == bool(rhs.base()) )
556 && ( ! base() || dip_equal( *base(), *rhs.base() ) );
559 bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const;
561 detail::IdType dereference() const;
566 /** Expert backdoor. */
567 detail::CDataiterator * get() const
568 { return _dip.get(); }
572 ///////////////////////////////////////////////////////////////////
574 /** \relates LookupAttr::iterator Stream output. */
575 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj );
577 ///////////////////////////////////////////////////////////////////
579 /** \name Helpers and forward declarations from LookupAttrTools.h */
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;
590 template<class _ResultT, class _AttrT>
594 /////////////////////////////////////////////////////////////////
596 ///////////////////////////////////////////////////////////////////
597 /////////////////////////////////////////////////////////////////
599 ///////////////////////////////////////////////////////////////////
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 );
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; }
608 #endif // ZYPP_SAT_LOOKUPATTR_H