ref: refs/heads/ma-tmp-pqt
commit a8f49f48e945464e6eb129ac157574053f17c13a
Author: Michael Andres
Date: Sat Apr 11 00:57:07 2009 +0200
Let PoolQuery::compile provide the AttrMatcher instead of compiling all the regexes on its own.
---
zypp/PoolQuery.cc | 195 +++++++++++++++++++----------------------------------
zypp/PoolQuery.h | 12 +++-
2 files changed, 79 insertions(+), 128 deletions(-)
diff --git a/zypp/PoolQuery.cc b/zypp/PoolQuery.cc
index 4b6a97e..c33ce96 100644
--- a/zypp/PoolQuery.cc
+++ b/zypp/PoolQuery.cc
@@ -83,6 +83,10 @@ namespace zypp
mutable AttrCompiledStrMap _rcattrs;
mutable AttrRegexMap _rattrs;
+ /** AttrMatcher per attribtue. */
+ typedef std::pairsat::SolvAttr,sat::AttrMatcher AttrMatchData;
+ mutable std::vector<AttrMatchData> _attrMatchList;
+
/** Edition condition operand */
mutable Edition _edition;
/** Operator for edition condition */
@@ -142,6 +146,7 @@ namespace zypp
void PoolQuery::Impl::compile() const
{
_cflags = _flags;
+ _attrMatchList.clear();
// 'different' - will have to iterate through all and match by ourselves (slow)
// 'same' - will pass the compiled string to dataiterator_init
@@ -156,7 +161,10 @@ namespace zypp
{
_rcstrings = createRegex(_strings);
if (_strings.size() > 1)
- _cflags = (_cflags & ~SEARCH_STRINGMASK) | SEARCH_REGEX;//setMatchRegex();
+ _cflags = (_cflags & ~SEARCH_STRINGMASK) | SEARCH_REGEX;
+
+ _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr,
+ sat::AttrMatcher( _rcstrings, _cflags ) ) );
}
// // ONE ATTRIBUTE
@@ -169,13 +177,18 @@ namespace zypp
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
_rcstrings = createRegex(joined);
- _rcattrs.insert(pair(_attrs.begin()->first, string()));
// switch to regex for multiple strings
if (joined.size() > 1)
_cflags = (_cflags & ~SEARCH_STRINGMASK) | SEARCH_REGEX;
+
+ _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first,
+ sat::AttrMatcher( _rcstrings, _cflags ) ) );
+ //---
+ _rcattrs.insert(pair(_attrs.begin()->first, string()));
if ((_cflags & SEARCH_STRINGMASK) == SEARCH_REGEX)
/* We feed multiple lines eventually (e.g. authors or descriptions), so set REG_NEWLINE. */
_regex = str::regex(_rcstrings, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | (_cflags & SEARCH_NOCASE ? REG_ICASE : 0));
+ //---
}
// // MULTIPLE ATTRIBUTES
@@ -231,17 +244,28 @@ attremptycheckend:
invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
_rcstrings = createRegex(joined);
}
+ //---
// copy the _attrs keys to _rcattrs
for_(ai, _attrs.begin(), _attrs.end())
_rcattrs.insert(pair(ai->first, string()));
+ //---
// switch to regex for multiple strings
if (joined.size() > 1)
_cflags = (_cflags & ~SEARCH_STRINGMASK) | SEARCH_REGEX;
+ // May use the same AttrMatcher for all
+ sat::AttrMatcher matcher( _rcstrings, _cflags );
+ for_( ai, _attrs.begin(), _attrs.end() )
+ {
+ _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
+ }
+
+ //---
if ((_cflags & SEARCH_STRINGMASK) == SEARCH_REGEX)
/* We feed multiple lines eventually (e.g. authors or descriptions), so set REG_NEWLINE. */
_regex = str::regex(_rcstrings, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | (_cflags & SEARCH_NOCASE ? REG_ICASE : 0));
+ //---
}
// // DIFFERENT STRINGS FOR DIFFERENT ATTRS
@@ -256,16 +280,24 @@ attremptycheckend:
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
string s = createRegex(joined);
+ //---
_rcattrs.insert(pair(ai->first, s));
+ //---
// switch to regex for multiple strings
if (joined.size() > 1)
_cflags = (_cflags & ~SEARCH_STRINGMASK) | SEARCH_REGEX;
+
+ _attrMatchList.push_back( AttrMatchData( ai->first,
+ sat::AttrMatcher( s, _cflags ) ) );
+
+ //---
if ((_cflags & SEARCH_STRINGMASK) == SEARCH_REGEX)
{
str::regex regex(s, REG_EXTENDED | REG_NOSUB | REG_NEWLINE | (_cflags & SEARCH_NOCASE ? REG_ICASE : 0));
_rattrs.insert(pair(ai->first, regex));
}
+ //---
}
}
}
@@ -1350,12 +1382,6 @@ attremptycheckend:
namespace detail
{ /////////////////////////////////////////////////////////////////
-//#define PQM_LOG_MATCHES
-
-#ifdef PQM_LOG_MATCHES
-#warning PQM_LOG_MATCHES debug loggin still enabled (slows down queries)
-#endif
-
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : PoolQueryMatcher
@@ -1373,6 +1399,9 @@ attremptycheckend:
* to the first match. Otherwise advance moves to the next match, or
* to the \ref end, if there is no more match.
*
+ * \note The original implementation treated an empty search string as
+ * <it>"match always"</it>. We stay compatible.
+ *
* \todo I guess the attribute content matching deserves some polishing,
* it's more or less taken from the old iterator.
*/
@@ -1380,7 +1409,7 @@ attremptycheckend:
{
public:
typedef sat::LookupAttr::iterator base_iterator;
- typedef std::pair StringMatchData;
+ typedef std::pairsat::SolvAttr,sat::AttrMatcher AttrMatchData;
public:
const base_iterator & end() const
@@ -1431,71 +1460,20 @@ attremptycheckend:
// Status restriction:
_status_flags = query_r->_status_flags;
- // Attribute content matching: (beautify it)
- _flags = query_r->_cflags;
- _str = query_r->_rcstrings;
- _regex = query_r->_regex;
- _attrs_str = query_r->_rcattrs;
- _attrs_regex = query_r->_rattrs;
-
+ // Attribute content matching:
// this setup depends on how PoolQuery::compile
// sets up the quert strings.
- if ( _attrs_str.empty() )
- {
- _matchList.push_back( StringMatchData( SolvAttr::allAttr, (_str.empty() ? 0 : _str.c_str() ) ) );
- _m.setSearchstring( _str, _flags );
- USR << _m << endl;
- }
- else if ( _attrs_str.size() == 1 )
- {
- _matchList.push_back( StringMatchData( _attrs_str.begin()->first, (_str.empty() ? 0 : _str.c_str() ) ) );
- _m.setSearchstring( _str, _flags );
- USR << _m << endl;
- }
- else
- {
- _m.setSearchstring( _str, _flags );
- bool doRegex = ( (_flags & SEARCH_STRINGMASK) == SEARCH_REGEX );
- for_( ai, _attrs_str.begin(), _attrs_str.end() )
- {
- if ( doRegex )
- {
- const regex_t * regex_p;
- if ( _str.empty() )
- {
- PoolQuery::AttrRegexMap::iterator rai = _attrs_regex.find( ai->first );
- if ( rai != _attrs_regex.end() )
- regex_p = rai->second.get();
- else
- {
- INT << "No compiled regex found for " << ai->first << endl;
- continue;
- }
- }
- else
- regex_p = _regex.get();
-
- _matchList.push_back( StringMatchData( ai->first, regex_p ) );
- }
- else
- {
- _matchList.push_back( StringMatchData( ai->first, (_str.empty() ? ai->second : _str).c_str() ) );
- }
- }
- }
+ _attrMatchList = query_r->_attrMatchList;
}
~PoolQueryMatcher()
- {
- SEC << "Match? " << _counter << endl;
- //
- }
+ {}
private:
/** Initialize a new base query. */
base_iterator startNewQyery() const
{
- sat::LookupAttr q( sat::SolvAttr::allAttr );
+ sat::LookupAttr q;
// Repo restriction:
if ( _repos.size() == 1 )
@@ -1503,12 +1481,18 @@ attremptycheckend:
// else: handled in isAMatch.
// Attribute restriction:
- if( !_attrs_str.empty() )
+ if ( _attrMatchList.size() == 1 ) // all or 1 attr
{
- // Jump to the 1st one, the rest is done in isAMatch.
- q.setAttr( _attrs_str.begin()->first );
- //q.setAttrMatcher( _m );
+ const AttrMatchData & matchData( _attrMatchList[0] );
+ q.setAttr( matchData.first );
+ if ( matchData.second ) // empty searchstring matches always
+ q.setAttrMatcher( matchData.second );
}
+ else // more than 1 attr (but not all)
+ {
+ // no restriction, it's all handled in isAMatch.
+ q.setAttr( sat::SolvAttr::allAttr );
+ }
return q.begin();
}
@@ -1526,7 +1510,6 @@ attremptycheckend:
*/
bool isAMatch( base_iterator & base_r ) const
{
- ++_counter;
/////////////////////////////////////////////////////////////////////
Repository inRepo( base_r.inRepo() );
// Status restriction:
@@ -1559,54 +1542,26 @@ attremptycheckend:
}
/////////////////////////////////////////////////////////////////////
// string matching:
- if( _attrs_str.empty() )
- {
- // search all attributes ;(
- const StringMatchData & data( *_matchList.begin() );
- sat::LookupAttr q( sat::SolvAttr::allAttr, inSolvable );
- for_( it, q.begin(), q.end() )
- if ( attrMatchString( it, data ) )
- return true;
+ if ( _attrMatchList.size() == 1 )
+ {
+ return true; // matching was done by the base iterator
}
- else
- {
- // base iterator always visits the current (first) attribute:
- std::vector<StringMatchData>::const_iterator mi( _matchList.begin() );
- if ( attrMatchString( base_r, *_matchList.begin() ) )
- return true;
- // then check the remaining ones:
- for_( mi, ++_matchList.begin(), _matchList.end() )
- {
- sat::LookupAttr q( mi->first, inSolvable );
- for_( it, q.begin(), q.end() )
- if ( attrMatchString( it, *mi ) )
- return true;
- }
- }
- base_r.nextSkipSolvable();
- return false;
- }
- private:
- /** */
- bool attrMatchString( const base_iterator & base_r, const StringMatchData & data_r ) const
- {
- //return true;
- return _m( base_r.c_str() );
- if ( ! data_r.second ) // empty string matches always
- return true;
-#ifdef PQM_LOG_MATCHES
- bool ret = ::dataiterator_match_obsolete( base_r.get(), _flags, data_r.second );
- if ( ret )
- DBG << "Match in " << base_r << endl;
- return ret;
-#else
- return ::dataiterator_match_obsolete( base_r.get(), _flags, data_r.second );
-#endif
+ // Here: search all attributes ;(
+ for_( mi, _attrMatchList.begin(), _attrMatchList.end() )
+ {
+ const AttrMatchData & matchData( *mi );
+ sat::LookupAttr q( matchData.first, inSolvable );
+ if ( matchData.second ) // empty searchstring matches always
+ q.setAttrMatcher( matchData.second );
+ if ( ! q.empty() )
+ return true;
+ }
+ base_r.nextSkipSolvable();
+ return false;
}
private:
- mutable DefaultIntegral _counter;
/** Repositories include in the search. */
std::set<Repository> _repos;
/** Resolvable kinds to include. */
@@ -1616,20 +1571,8 @@ attremptycheckend:
Edition _edition;
/** Installed status filter flags. \see PoolQuery::StatusFilter */
int _status_flags;
-
- /** string matching option flags */
- int _flags;
- /** global query string compiled */
- std::string _str;
- /** global query compiled regex */
- str::regex _regex;
- /** Attribute to string map holding per-attribute query strings (compiled) */
- PoolQuery::AttrCompiledStrMap _attrs_str;
- /** Attribute to regex map holding per-attribute compiled regex */
- PoolQuery::AttrRegexMap _attrs_regex;
- /** Prepared dataiterator_match_obsolete args */
- std::vector<StringMatchData> _matchList;
- sat::AttrMatcher _m;
+ /** AttrMatcher per attribtue. */
+ std::vector<AttrMatchData> _attrMatchList;
};
///////////////////////////////////////////////////////////////////
diff --git a/zypp/PoolQuery.h b/zypp/PoolQuery.h
index c3c6045..6eb82d2 100644
--- a/zypp/PoolQuery.h
+++ b/zypp/PoolQuery.h
@@ -236,7 +236,11 @@ namespace zypp
*/
- /** \name Text Matching Options */
+ /** \name Text Matching Options
+ * \note The implementation treats an empty search string as
+ * <it>"match always"</it>. So if you want to actually match
+ * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
+ */
//@{
/**
* Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
@@ -424,9 +428,13 @@ namespace zypp
private:
friend class boost::iterator_core_access;
+
+ sat::Solvable dereference() const
+ { return base_reference().inSolvable(); }
+
void increment();
- private:
+ private:
shared_ptr<PoolQueryMatcher> _matcher;
};
///////////////////////////////////////////////////////////////////
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org
For additional commands, e-mail: zypp-commit+help@opensuse.org