[zypp-commit] <libzypp> master : Enhance PoolQueryIterator to allow detailed inspection attribute matches.
ref: refs/heads/master commit 1184bb3499ef3e6942ad6026f9d9135726e97521 Author: Michael Andres <ma@suse.de> Date: Thu Jun 25 16:17:26 2009 +0200 Enhance PoolQueryIterator to allow detailed inspection attribute matches. --- zypp/PoolQuery.cc | 99 ++++++++++++++++++++++++++++++++++++++++++++---- zypp/PoolQuery.h | 77 ++++++++++++++++++++++++++++++++++++- zypp/sat/LookupAttr.cc | 6 +++ zypp/sat/LookupAttr.h | 8 +++- 4 files changed, 178 insertions(+), 12 deletions(-) diff --git a/zypp/PoolQuery.cc b/zypp/PoolQuery.cc index 375a349..79f5ee6 100644 --- a/zypp/PoolQuery.cc +++ b/zypp/PoolQuery.cc @@ -1217,21 +1217,71 @@ attremptycheckend: if ( base_r == end() ) base_r = startNewQyery(); // first candidate else + { + base_r.nextSkipSolvable(); // assert we don't visit this Solvable again ++base_r; // advance to next candidate + } while ( base_r != end() ) { if ( isAMatch( base_r ) ) - { - base_r.nextSkipSolvable(); // assert we don't visit this Solvable again return true; - } // No match: try next - ++base_r; + ++base_r; } return false; } + /** Provide all matching attributes within this solvable. + * + */ + void matchDetail( const base_iterator & base_r, std::vector<base_iterator> & return_r ) const + { + if ( base_r == end() ) + return; + + sat::Solvable inSolvable( base_r.inSolvable() ); + + if ( _attrMatchList.size() == 1 ) + { + // base_r is already on the 1st matching attribute! + // String matching is done by the base iterator. We must check the predicate here. + // Let's see if there are more matches for this solvable: + base_iterator base( base_r ); + base.stayInThisSolvable(); // avoid discarding matches we found far away from here. + return_r.push_back( base ); + + const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate ); + for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end() + { + if ( ! predicate || predicate( base ) ) + return_r.push_back( base ); + } + } + else + { + // Here: search all attributes ;( + for_( mi, _attrMatchList.begin(), _attrMatchList.end() ) + { + const AttrMatchData & matchData( *mi ); + sat::LookupAttr q( matchData.attr, inSolvable ); + if ( matchData.attrMatcher ) // an empty searchstring matches always + q.setAttrMatcher( matchData.attrMatcher ); + + if ( ! q.empty() ) // there are matches. + { + // now check any predicate: + const AttrMatchData::Predicate & predicate( matchData.predicate ); + for_( it, q.begin(), q.end() ) + { + if ( ! predicate || predicate( it ) ) + return_r.push_back( it ); + } + } + } + } + } + public: /** Ctor stores the \ref PoolQuery settings. * \throw MatchException Any of the exceptions thrown by \ref PoolQuery::Impl::compile. @@ -1344,8 +1394,7 @@ attremptycheckend: if ( ! predicate || predicate( base_r ) ) return true; - base_r.nextSkipSolvable(); - return false; + return false; // no skip as there may be more occurrences od this attr. } // Here: search all attributes ;( @@ -1396,8 +1445,42 @@ attremptycheckend: // matcher restarts if at end! It is called from the ctor // to get the 1st match. But if the end is reached, it should // be deleted, otherwise we'd start over again. - if ( _matcher && ! _matcher->advance( base_reference() ) ) - _matcher.reset(); + if ( !_matcher ) + return; // at end + if ( _matches ) + _matches.reset(); // invalidate old matches + if ( ! _matcher->advance( base_reference() ) ) + _matcher.reset(); + } + + const PoolQueryIterator::Matches & PoolQueryIterator::matches() const + { + if ( _matches ) + return *_matches; + + if ( !_matcher ) + { + // at end of query: + static const Matches _none; + return _none; + } + + _matches.reset( new Matches ); + _matcher->matchDetail( base_reference(), *_matches ); + return *_matches; + } + + std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj ) + { + str << *obj; + if ( ! obj.matchesEmpty() ) + { + for_( it, obj.matchesBegin(), obj.matchesEnd() ) + { + str << endl << " " << it->inSolvAttr() << "\t" << it->asString(); + } + } + return str; } /////////////////////////////////////////////////////////////////// diff --git a/zypp/PoolQuery.h b/zypp/PoolQuery.h index 032650c..4238155 100644 --- a/zypp/PoolQuery.h +++ b/zypp/PoolQuery.h @@ -77,6 +77,7 @@ namespace zypp * on kinds, multiple repos, and multiple attributes are filtered inside * the PoolQuery, so these tend to be slower. * + * \see detail::PoolQueryIterator on how to inspect matches in detail. * \see tests/zypp/PoolQuery_test.cc for more examples * \see sat::SolvIterMixin */ @@ -463,7 +464,6 @@ namespace zypp /** \relates PoolQuery Stream output. */ std::ostream & operator<<( std::ostream & str, const PoolQuery & obj ); - /////////////////////////////////////////////////////////////////// namespace detail { ///////////////////////////////////////////////////////////////// @@ -475,7 +475,12 @@ namespace zypp // CLASS NAME : PoolQuery::PoolQueryIterator // /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin. - */ + * + * The \ref PoolQueryIterator visits sat::Solavables that do contain matches. + * + * But it also provides an iterator by itself, to allow a detailed inspection of + * the individual attribute matches within the current Solvable. + */ class PoolQueryIterator : public boost::iterator_adaptor< PoolQueryIterator // Derived , sat::LookupAttr::iterator // Base @@ -484,6 +489,10 @@ namespace zypp , const sat::Solvable // Reference
{ + typedef std::vector<sat::LookupAttr::iterator> Matches; + public: + typedef Matches::size_type size_type; + typedef Matches::const_iterator matches_iterator; public: /** Default ctor is also \c end.*/ PoolQueryIterator() @@ -494,6 +503,61 @@ namespace zypp : _matcher( matcher_r ) { increment(); } + /** \name Detailed inspection of attribute matches within the current Solvable. + * + * The \ref matches_iterator visits all attribute matches within the current Solvable, + * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a + * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced, + * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query + * ended. + * + * \code + * // Setup query for "libzypp" in name or requires: + * PoolQuery q; + * q.addString( "libzypp" ); + * q.setMatchSubstring(); + * q.setCaseSensitive( false ); + * q.addAttribute( sat::SolvAttr::name ); + * q.addDependency( sat::SolvAttr::requires ); + * + * // Iterate the result: + * for_( solvIter, q.begin(), q.end() ) + * { + * sat::Solvable solvable( *solvIter ); + * cout << "Found matches in " << solvable << endl; + * if ( verbose ) + * for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() ) + * { + * sat::LookupAttr::iterator attr( *attrIter ); + * cout << " " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl; + * } + * } + * + * + * Found matches in PackageKit-0.3.11-1.12.i586(@System) + * solvable:requires "libzypp.so.523" + * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System) + * solvable:requires "libzypp.so.523" + * solvable:requires "libzypp >= 5.25.3-0.1.2" + * Found matches in libzypp-5.30.3-0.1.1.i586(@System) + * solvable:name "libzypp" + * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System) + * solvable:name "libzypp-testsuite-tools" + * solvable:requires "libzypp.so.523" + * ... + * \endcode + */ + //@{ + /** \c False unless this is the \c end iterator. */ + bool matchesEmpty() const { return ! _matcher; } + /** Number of attribute matches. */ + size_type matchesSize() const { return matches().size(); } + /** Begin of matches. */ + matches_iterator matchesBegin() const { return matches().begin(); } + /** End of matches. */ + matches_iterator matchesEnd() const { return matches().end(); } + //@} + private: friend class boost::iterator_core_access; @@ -502,8 +566,12 @@ namespace zypp void increment(); - private: + private: + const Matches & matches() const; + + private: shared_ptr<PoolQueryMatcher> _matcher; + mutable shared_ptr<Matches> _matches; }; /////////////////////////////////////////////////////////////////// @@ -511,6 +579,9 @@ namespace zypp inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj ) { return str << obj.base(); } + /** \relates PoolQueryIterator Detailed stream output. */ + std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj ); + /////////////////////////////////////////////////////////////////// } //namespace detail /////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/LookupAttr.cc b/zypp/sat/LookupAttr.cc index cd8cada..f184502 100644 --- a/zypp/sat/LookupAttr.cc +++ b/zypp/sat/LookupAttr.cc @@ -350,6 +350,12 @@ namespace zypp void LookupAttr::iterator::nextSkipRepo() { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); } + void LookupAttr::iterator::stayInThisSolvable() + { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } } + + void LookupAttr::iterator::stayInThisRepo() + { if ( _dip ) { _dip.get()->repoid = -1; } } + /////////////////////////////////////////////////////////////////// // attr value type test /////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/LookupAttr.h b/zypp/sat/LookupAttr.h index 34a3ecd..3152b11 100644 --- a/zypp/sat/LookupAttr.h +++ b/zypp/sat/LookupAttr.h @@ -214,7 +214,7 @@ namespace zypp // // CLASS NAME : LookupRepoAttr // - /** Lightweight repositor attribute value lookup. + /** Lightweight repository attribute value lookup. * * This is just a convenience class that overloads all * \ref LookupAttr methods which take a \ref LookupAttr::Location @@ -357,6 +357,12 @@ namespace zypp /** Immediately advance to the next \ref Repository. */ void skipRepo() { nextSkipRepo(); increment(); } + + /** Stop after all matches in the current \ref Solvable are processed. */ + void stayInThisSolvable(); + + /** Stop after all matches in the current \ref Repository are processed. */ + void stayInThisRepo(); //@} /** \name Current position info. */ -- To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org For additional commands, e-mail: zypp-commit+help@opensuse.org
participants (1)
-
Michael Andres