Impl()
: _flags( Match::SUBSTRING | Match::NOCASE | Match::SKIP_KIND )
, _match_word(false)
- , _require_all(false)
, _status_flags(ALL)
{}
/** Sat solver search flags */
Match _flags;
bool _match_word;
- bool _require_all;
/** Sat solver status flags */
StatusFilter _status_flags;
&& _attrs == rhs._attrs
&& _uncompiledPredicated == rhs._uncompiledPredicated
&& _match_word == rhs._match_word
- && _require_all == rhs._require_all
&& _status_flags == rhs._status_flags
&& _edition == rhs._edition
&& _op == rhs._op
mutable AttrMatchList _attrMatchList;
private:
- /** Pass flags from \ref compile, as they may have been changed. */
- string createRegex( const StrContainer & container, const Match & flags ) const;
+ /** Join patterns in \a container_r according to \a flags_r into a single \ref StrMatcher.
+ * The \ref StrMatcher returned will be a REGEX if more than one pattern was passed.
+ */
+ StrMatcher joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const;
private:
friend Impl * rwcowClone<Impl>( const Impl * rhs );
{
_attrMatchList.clear();
- Match cflags( _flags );
- if ( cflags.mode() == Match::OTHER ) // this will never succeed...
- ZYPP_THROW( MatchUnknownModeException( cflags ) );
-
- /** Compiled search strings. */
- string rcstrings;
-
+ if ( _flags.mode() == Match::OTHER ) // this will never succeed...
+ ZYPP_THROW( MatchUnknownModeException( _flags ) );
// 'different' - will have to iterate through all and match by ourselves (slow)
// 'same' - will pass the compiled string to dataiterator_init
StrContainer joined;
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
- rcstrings = createRegex(joined, cflags);
- if (joined.size() > 1) // switch to regex for multiple strings
- cflags.setModeRegex();
- _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first,
- StrMatcher( rcstrings, cflags ) ) );
+
+ _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first, joinedStrMatcher( joined, _flags ) ) );
}
// // MULTIPLE ATTRIBUTES
{
// check whether there are any per-attribute strings
bool attrvals_empty = true;
- for (AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
- if (!ai->second.empty())
- for(StrContainer::const_iterator it = ai->second.begin();
- it != ai->second.end(); it++)
- if (!it->empty())
- {
- attrvals_empty = false;
- goto attremptycheckend;
- }
-attremptycheckend:
+ for_( ai, _attrs.begin(), _attrs.end() )
+ {
+ if ( ai->second.empty() )
+ continue;
+ for_( it, ai->second.begin(), ai->second.end() )
+ {
+ if ( !it->empty() )
+ {
+ attrvals_empty = false;
+ break;
+ }
+ }
+ if ( ! attrvals_empty )
+ break;
+ }
// chceck whether the per-attribute strings are all the same
bool attrvals_thesame = true;
if (attrvals_empty)
{
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
- rcstrings = createRegex(joined, cflags);
}
else
{
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
- rcstrings = createRegex(joined, cflags);
}
- if (joined.size() > 1) // switch to regex for multiple strings
- cflags.setModeRegex();
+
// May use the same StrMatcher for all
- StrMatcher matcher( rcstrings, cflags );
+ StrMatcher matcher( joinedStrMatcher( joined, _flags ) );
for_( ai, _attrs.begin(), _attrs.end() )
{
_attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
StrContainer joined;
invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
- string s = createRegex(joined, cflags);
- if (joined.size() > 1) // switch to regex for multiple strings
- cflags.setModeRegex();
- _attrMatchList.push_back( AttrMatchData( ai->first,
- StrMatcher( s, cflags ) ) );
+
+ _attrMatchList.push_back( AttrMatchData( ai->first, joinedStrMatcher( joined, _flags ) ) );
}
}
}
if ( ! mstr.empty() )
joined.insert( mstr );
- cflags = _flags;
- rcstrings = createRegex( joined, cflags );
- if ( joined.size() > 1 ) // switch to regex for multiple strings
- cflags.setModeRegex();
-
- _attrMatchList.push_back( AttrMatchData( it->attr,
- StrMatcher( rcstrings, cflags ),
- it->predicate, it->predicateStr ) );
+ // copy and exchange the StrMatcher
+ AttrMatchData nattr( *it );
+ nattr.strMatcher = joinedStrMatcher( joined, _flags );
+ _attrMatchList.push_back( std::move(nattr) );
}
else
{
// If no attributes defined at all, then add 'query all'
if ( _attrMatchList.empty() )
{
- cflags = _flags;
- rcstrings = createRegex( _strings, cflags );
- if ( _strings.size() > 1 ) // switch to regex for multiple strings
- cflags.setModeRegex();
- _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr,
- StrMatcher( rcstrings, cflags ) ) );
+ _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr, joinedStrMatcher( _strings, _flags ) ) );
}
// Finally check here, whether all involved regex compile.
//DBG << asString() << endl;
}
-
- /**
- * Converts '*' and '?' wildcards within str into their regex equivalents.
- */
- static string wildcards2regex(const string & str)
- {
- string regexed = str;
-
- string r_all(".*"); // regex equivalent of '*'
- string r_one("."); // regex equivalent of '?'
- string::size_type pos;
-
- // replace all "*" in input with ".*"
- for (pos = 0; (pos = regexed.find("*", pos)) != std::string::npos; pos+=2)
- regexed = regexed.replace(pos, 1, r_all);
-
- // replace all "?" in input with "."
- for (pos = 0; (pos = regexed.find('?', pos)) != std::string::npos; ++pos)
- regexed = regexed.replace(pos, 1, r_one);
-
- return regexed;
- }
-
- string PoolQuery::Impl::createRegex( const StrContainer & container, const Match & flags ) const
+ ///////////////////////////////////////////////////////////////////
+ namespace
{
-//! macro for word boundary tags for regexes
-#define WB (_match_word ? string("\\b") : string())
- string rstr;
-
- if (container.empty())
- return rstr;
-
- if (container.size() == 1)
+ /** Escape \a str_r for use in a regex.
+ * \a flags_r determines whether the input string is interpreted
+ * as regex, glob or plain string.
+ */
+ std::string rxEscape( std::string str_r, const Match & flags_r )
{
- return WB + *container.begin() + WB;
- }
-
- // multiple strings
+ if ( str_r.empty() || flags_r.isModeRegex() )
+ return str_r;
- bool use_wildcards = flags.isModeGlob();
- StrContainer::const_iterator it = container.begin();
- string tmp;
+ if ( flags_r.isModeGlob() )
+ return str::rxEscapeGlob( std::move(str_r) );
- if (use_wildcards)
- tmp = wildcards2regex(*it);
- else
- tmp = *it;
-
- if (_require_all)
- {
- if ( ! flags.isModeString() ) // not match exact
- tmp += ".*" + WB + tmp;
- rstr = "(?=" + tmp + ")";
+ return str::rxEscapeStr( std::move(str_r) );
}
- else
- {
- if ( flags.isModeString() || flags.isModeGlob() )
- rstr = "^";
- rstr += WB + "(" + tmp;
- }
-
- ++it;
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
- for (; it != container.end(); ++it)
+ StrMatcher PoolQuery::Impl::joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const
+ {
+ if ( container_r.empty() )
+ return StrMatcher( std::string(), flags_r );
+
+ if ( container_r.size() == 1 && !_match_word ) // use RX to match words
+ return StrMatcher( *container_r.begin(), flags_r );
+
+ // Convert to a regex.
+ // Note: Modes STRING and GLOB match whole strings (anchored ^ $)
+ // SUBSTRING and REGEX match substrings (match_word anchores SUBSTRING \b)
+ Match retflags( flags_r );
+ retflags.setModeRegex();
+ str::Str ret;
+
+ if ( flags_r.isModeString() || flags_r.isModeGlob() )
+ ret << "^";
+ else if ( _match_word )
+ ret << "\\b";
+
+ // (..|..|..)
+ char sep = '(';
+ for ( const::std::string & s : container_r )
{
- if (use_wildcards)
- tmp = wildcards2regex(*it);
- else
- tmp = *it;
-
- if (_require_all)
- {
- if ( ! flags.isModeString() ) // not match exact
- tmp += ".*" + WB + tmp;
- rstr += "(?=" + tmp + ")";
- }
- else
- {
- rstr += "|" + tmp;
- }
+ ret << sep << rxEscape( s, flags_r );
+ if ( sep == '(' )
+ sep = '|';
}
+ ret << ')';
- if (_require_all)
- {
- if ( ! flags.isModeString() ) // not match exact
- rstr += WB + ".*";
- }
- else
- {
- rstr += ")" + WB;
- if ( flags.isModeString() || flags.isModeGlob() )
- rstr += "$";
- }
+ if ( flags_r.isModeString() || flags_r.isModeGlob() )
+ ret << "$";
+ else if ( _match_word )
+ ret << "\\b";
- return rstr;
-#undef WB
+ return StrMatcher( ret, retflags );
}
string PoolQuery::Impl::asString() const
_pimpl->_op = op;
}
- void PoolQuery::setMatchSubstring() { _pimpl->_flags.setModeSubstring(); }
- void PoolQuery::setMatchExact() { _pimpl->_flags.setModeString(); }
- void PoolQuery::setMatchRegex() { _pimpl->_flags.setModeRegex(); }
- void PoolQuery::setMatchGlob() { _pimpl->_flags.setModeGlob(); }
- void PoolQuery::setMatchWord()
- {
- _pimpl->_match_word = true;
- _pimpl->_flags.setModeRegex();
- }
+ void PoolQuery::setMatchSubstring() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = false; }
+ void PoolQuery::setMatchExact() { _pimpl->_flags.setModeString(); _pimpl->_match_word = false; }
+ void PoolQuery::setMatchRegex() { _pimpl->_flags.setModeRegex(); _pimpl->_match_word = false; }
+ void PoolQuery::setMatchGlob() { _pimpl->_flags.setModeGlob(); _pimpl->_match_word = false; }
+ void PoolQuery::setMatchWord() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = true; }
Match PoolQuery::flags() const
{ return _pimpl->_flags; }
{ _pimpl->_status_flags = flags; }
- void PoolQuery::setRequireAll(bool require_all)
- { _pimpl->_require_all = require_all; }
-
-
const PoolQuery::StrContainer &
PoolQuery::strings() const
{ return _pimpl->_strings; }
{ _pimpl->_flags.turn( Match::FILES, value ); }
bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); }
- bool PoolQuery::matchSubstring() const { return _pimpl->_flags.isModeSubstring(); }
+ bool PoolQuery::matchSubstring() const { return _pimpl->_flags.isModeSubstring() && !_pimpl->_match_word; }
bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); }
bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); }
-
- bool PoolQuery::matchWord() const
- { return _pimpl->_match_word; }
-
- bool PoolQuery::requireAll() const
- { return _pimpl->_require_all; }
+ bool PoolQuery::matchWord() const { return _pimpl->_flags.isModeSubstring() && _pimpl->_match_word; }
PoolQuery::StatusFilter PoolQuery::statusFilterFlags() const
{ return _pimpl->_status_flags; }
{ invokeOnEach( begin(), end(), fnc); }
+ /*DEPRECATED LEGACY:*/void PoolQuery::setRequireAll( bool ) {}
+ /*DEPRECATED LEGACY:*/bool PoolQuery::requireAll() const { return false; }
+
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : PoolQuery::Attr
static const PoolQueryAttr kindAttr;
static const PoolQueryAttr stringAttr;
static const PoolQueryAttr stringTypeAttr;
- static const PoolQueryAttr requireAllAttr;
+ static const PoolQueryAttr requireAllAttr; // LEAGACY: attribute was defined but never implemented.
static const PoolQueryAttr caseSensitiveAttr;
static const PoolQueryAttr installStatusAttr;
static const PoolQueryAttr editionAttr;
const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
- const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all");
+ const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all"); // LEAGACY: attribute was defined but never implemented.
const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
const PoolQueryAttr PoolQueryAttr::editionAttr("version");
}
else if ( attribute==PoolQueryAttr::requireAllAttr )
{
- if ( str::strToTrue(attrValue) )
- {
- setRequireAll(true);
- }
- else if ( !str::strToFalse(attrValue) )
- {
- setRequireAll(false);
- }
- else
- {
- WAR << "unknown boolean value " << attrValue << endl;
- }
+ // LEAGACY: attribute was defined but never implemented.
+ // Actually it should not occur outside our testcases.
}
else if ( attribute==PoolQueryAttr::caseSensitiveAttr )
{
}
}
- if( requireAll() != q.requireAll() )
- {
- str << "require_all: ";
- if (requireAll())
- {
- str << "on" << delim;
- }
- else
- {
- str << "off" << delim;
- }
- }
-
if( statusFilterFlags() != q.statusFilterFlags() )
{
switch( statusFilterFlags() )