namespace
{ /////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////
+ // some Helpers and Predicates
+ /////////////////////////////////////////////////////////////////
+
+ bool isDependencyAttribute( sat::SolvAttr attr_r )
+ {
+ static sat::SolvAttr deps[] = {
+ SolvAttr::provides,
+ SolvAttr::requires,
+ SolvAttr::recommends,
+ SolvAttr::obsoletes,
+ SolvAttr::conflicts,
+ SolvAttr::suggests,
+ SolvAttr::supplements,
+ SolvAttr::enhances,
+ };
+ for_( it, arrayBegin(deps), arrayEnd(deps) )
+ if ( *it == attr_r )
+ return true;
+ return false;
+ }
+
+ /** Whether the current capabilities edition range ovelaps.
+ * Query asserts \a iter_r points to a capability and we
+ * have to check the range only.
+ */
+ struct EditionRangePredicate
+ {
+ EditionRangePredicate( const Rel & op, const Edition & edition )
+ : _range( op, edition )
+ {}
+
+ bool operator()( sat::LookupAttr::iterator iter_r )
+ {
+ CapDetail cap( iter_r.id() );
+ if ( ! cap.isSimple() )
+ return false;
+ if ( cap.isNamed() ) // no range to match
+ return true;
+ return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range );
+ }
+
+ std::string serialize() const
+ {
+ std::string ret( "EditionRange" );
+ str::appendEscaped( ret, _range.op.asString() );
+ str::appendEscaped( ret, _range.value.asString() );
+ return ret;
+ }
+
+ Edition::MatchRange _range;
+ };
+
+ /** Whether the current Solvables edition is within a given range. */
+ struct SolvableRangePredicate
+ {
+ SolvableRangePredicate( const Rel & op, const Edition & edition )
+ : _range( op, edition )
+ {}
+
+ bool operator()( sat::LookupAttr::iterator iter_r )
+ {
+ return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range );
+ }
+
+ std::string serialize() const
+ {
+ std::string ret( "SolvableRange" );
+ str::appendEscaped( ret, _range.op.asString() );
+ str::appendEscaped( ret, _range.value.asString() );
+ return ret;
+ }
+
+ Edition::MatchRange _range;
+ };
+
+ /** Whether the current capability matches a given one.
+ * Query asserts \a iter_r points to a capability and we
+ * have to check the match only.
+ */
+ struct CapabilityMatchPredicate
+ {
+ CapabilityMatchPredicate( Capability cap_r )
+ : _cap( cap_r )
+ {}
+
+ bool operator()( sat::LookupAttr::iterator iter_r ) const
+ {
+ return _cap.matches( iter_r.asType<Capability>() ) == CapMatch::yes;
+ }
+
+ std::string serialize() const
+ {
+ std::string ret( "CapabilityMatch" );
+ str::appendEscaped( ret, _cap.asString() );
+ return ret;
+ }
+
+ Capability _cap;
+ };
+
+ /////////////////////////////////////////////////////////////////
+ //
+ /////////////////////////////////////////////////////////////////
/** Match data per attribtue.
*
* This includes the attribute itself, an optional \ref sat::AttrMatcher
static bool always( sat::LookupAttr::iterator ) { return true; }
static bool never( sat::LookupAttr::iterator ) { return false; }
+ AttrMatchData()
+ {}
+
AttrMatchData( sat::SolvAttr attr_r, const sat::AttrMatcher & attrMatcher_r )
: attr( attr_r )
, attrMatcher( attrMatcher_r )
, predicateStr( predicateStr_r )
{}
- /** A usable Predicate must provide a string representation.
+ /** A usable Predicate must provide a string serialization.
* As there is no \c operator== for \ref Predicate, we compare it's
- * string representation instead. Actually Predicate deserves to become
- * a class which is also serializable, so we can store predicated queries.
+ * string representation instead. If you add new predicated, check the
+ * deserialization code in \ref deserialize.
*/
template<class _Predicate>
void addPredicate( const _Predicate & predicate_r )
{
predicate = predicate_r;
- predicateStr = predicate_r.stringRep();
+ predicateStr = predicate_r.serialize();
+ }
+
+ /** Dumb serialization.
+ * \code
+ * AttrMatchData ATTRIBUTE SEARCHSTRING [C|X] SERIALIZED_PREDICATE
+ * \endcode
+ */
+ std::string serialize() const
+ {
+ std::string ret( "AttrMatchData" );
+ str::appendEscaped( ret, attr.asString() );
+ str::appendEscaped( ret, attrMatcher.searchstring() );
+ // TODO: Actually the flag should be serialized too, but for PoolQuery
+ // it's by now sufficient to differ between mode OTHER and others,
+ // i.e. whether to compile or not compile.
+ str::appendEscaped( ret, attrMatcher.flags().mode() == Match::OTHER ? "C" : "X" );
+ str::appendEscaped( ret, predicateStr );
+ return ret;
}
+ /** Dumb restore from serialized string.
+ * \throw Exception on parse error.
+ */
+ static AttrMatchData deserialize( const std::string & str_r )
+ {
+ std::vector<std::string> words;
+ str::splitEscaped( str_r, std::back_inserter(words) );
+ if ( words.empty() || words[0] != "AttrMatchData" )
+ ZYPP_THROW( Exception( str::Str() << "Expecting AttrMatchData: " << str_r ) );
+ if ( words.size() != 5 )
+ ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
+
+ AttrMatchData ret;
+ ret.attr = sat::SolvAttr( words[1] );
+ ret.attrMatcher = sat::AttrMatcher( words[2] );
+ if ( words[3] == "C" )
+ ret.attrMatcher.setFlags( Match::OTHER );
+ ret.predicateStr = words[4];
+
+ // now the predicate
+ words.clear();
+ str::splitEscaped( ret.predicateStr, std::back_inserter(words) );
+ if ( ! words.empty() )
+ {
+ if ( words[0] == "EditionRange" )
+ {
+ if ( words.size() != 3 )
+ ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
+ ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]) );
+ }
+ else if ( words[0] == "SolvableRange" )
+ {
+ if ( words.size() != 3 )
+ ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
+ ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]) );
+ }
+ else if ( words[0] == "CapabilityMatch" )
+ {
+ if ( words.size() != 2 )
+ ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) );
+ ret.predicate = CapabilityMatchPredicate( Capability(words[1]) );
+ }
+ else
+ ZYPP_THROW( Exception( str::Str() << "Unknown predicate: " << str_r ) );
+ }
+ return ret;
+ }
+
sat::SolvAttr attr;
sat::AttrMatcher attrMatcher;
Predicate predicate;
typedef std::list<AttrMatchData> AttrMatchList;
- /////////////////////////////////////////////////////////////////
- // some Helpers and Predicates
- /////////////////////////////////////////////////////////////////
-
- bool isDependencyAttribute( sat::SolvAttr attr_r )
- {
- static sat::SolvAttr deps[] = {
- SolvAttr::provides,
- SolvAttr::requires,
- SolvAttr::recommends,
- SolvAttr::obsoletes,
- SolvAttr::conflicts,
- SolvAttr::suggests,
- SolvAttr::supplements,
- SolvAttr::enhances,
- };
- for_( it, arrayBegin(deps), arrayEnd(deps) )
- if ( *it == attr_r )
- return true;
- return false;
- }
-
- /** Whether the current capabilities edition range ovelaps.
- * Query asserts \a iter_r points to a capability and we
- * have to check the range only.
- */
- struct EditionRangePredicate
- {
- EditionRangePredicate( const Rel & op, const Edition & edition )
- : _range( op, edition )
- {}
-
- bool operator()( sat::LookupAttr::iterator iter_r )
- {
- CapDetail cap( iter_r.id() );
- if ( ! cap.isSimple() )
- return false;
- if ( cap.isNamed() ) // no range to match
- return true;
- return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range );
- }
-
- std::string stringRep() const
- {
- std::ostringstream str;
- str << "EditionRange " << _range.op << " " << _range.value;
- return str.str();
- }
-
- Edition::MatchRange _range;
- };
-
- /** Whether the current Solvables edition is within a given range. */
- struct SolvableRangePredicate
- {
- SolvableRangePredicate( const Rel & op, const Edition & edition )
- : _range( op, edition )
- {}
-
- bool operator()( sat::LookupAttr::iterator iter_r )
- {
- return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range );
- }
-
- std::string stringRep() const
- {
- std::ostringstream str;
- str << "SolvableRange " << _range.op << " " << _range.value;
- return str.str();
- }
-
- Edition::MatchRange _range;
- };
-
- /** Whether the current capability matches a given one.
- * Query asserts \a iter_r points to a capability and we
- * have to check the match only.
- */
- struct CapabilityMatchPredicate
- {
- CapabilityMatchPredicate( Capability cap_r )
- : _cap( cap_r )
- {}
-
- bool operator()( sat::LookupAttr::iterator iter_r ) const
- {
- return _cap.matches( iter_r.asType<Capability>() ) == CapMatch::yes;
- }
-
- std::string stringRep() const
- {
- std::ostringstream str;
- str << "CapabilityMatch " << _cap;
- return str.str();
- }
-
- Capability _cap;
- };
} /////////////////////////////////////////////////////////////////
// namespace
_attrMatchList.clear();
Match cflags( _flags );
- if ( cflags.mode() == Match::OTHER) // this will never succeed...
+ if ( cflags.mode() == Match::OTHER ) // this will never succeed...
ZYPP_THROW( MatchUnknownModeException( cflags ) );
/** Compiled search strings. */
static const PoolQueryAttr caseSensitiveAttr;
static const PoolQueryAttr installStatusAttr;
static const PoolQueryAttr editionAttr;
+ static const PoolQueryAttr complexAttr;
};
const PoolQueryAttr PoolQueryAttr::noAttr;
const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
const PoolQueryAttr PoolQueryAttr::editionAttr("version");
+ const PoolQueryAttr PoolQueryAttr::complexAttr("complex");
class StringTypeAttr : public IdStringType<PoolQueryAttr>
{
//\TODO maybe ctor with stream can be usefull
+ //\TODO let it throw, let it throw, let it throw.
bool PoolQuery::recover( istream &str, char delim )
{
bool finded_something = false; //indicates some atributes is finded
setEdition(Edition(attrValue), rel);
}
+ else if ( attribute == PoolQueryAttr::complexAttr )
+ {
+ try
+ {
+ _pimpl->_uncompiledPredicated.insert( AttrMatchData::deserialize( attrValue ) );
+ }
+ catch ( const Exception & err )
+ {
+ WAR << "Unparsable value for complex: " << err.asUserHistory() << endl;
+
+ }
+ }
else if ( attribute==PoolQueryAttr::noAttr )
{
WAR << "empty attribute name" << endl;
}
}
+ for_( it, _pimpl->_uncompiledPredicated.begin(), _pimpl->_uncompiledPredicated.end() )
+ {
+ str << "complex: "<< it->serialize() << delim;
+ }
+
//separating delim - protection
str << delim;
}