Kaynağa Gözat

add an API for cache filters/matcher

A lot of code deals with iterating over packages and checking for
specific states. At the moment these are all handcrafted inplace, but
that makes sharing common code which just differs in the states it
checks rather difficult and is error prune. Having an API to construct
arbitrary complex filters will come in handy for those.

Git-Dch: Ignore
David Kalnischkies 12 yıl önce
ebeveyn
işleme
3721cb019f
2 değiştirilmiş dosya ile 209 ekleme ve 52 silme
  1. 119 25
      apt-pkg/cachefilter.cc
  2. 90 27
      apt-pkg/cachefilter.h

+ 119 - 25
apt-pkg/cachefilter.cc

@@ -6,6 +6,7 @@
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <config.h>
 #include <config.h>
 
 
+#include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefilter.h>
 #include <apt-pkg/cachefilter.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
@@ -22,7 +23,11 @@
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
-PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d(NULL) {/*{{{*/
+APT_CONST Matcher::~Matcher() {}
+APT_CONST PackageMatcher::~PackageMatcher() {}
+
+// Name matches RegEx							/*{{{*/
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {
 	pattern = new regex_t;
 	pattern = new regex_t;
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	if (Res == 0)
 	if (Res == 0)
@@ -34,41 +39,36 @@ PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d
 	regerror(Res, pattern, Error, sizeof(Error));
 	regerror(Res, pattern, Error, sizeof(Error));
 	_error->Error(_("Regex compilation error - %s"), Error);
 	_error->Error(_("Regex compilation error - %s"), Error);
 }
 }
-									/*}}}*/
-bool PackageNameMatchesRegEx::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::PkgIterator const &Pkg) {
 	if (unlikely(pattern == NULL))
 	if (unlikely(pattern == NULL))
 		return false;
 		return false;
 	else
 	else
 		return regexec(pattern, Pkg.Name(), 0, 0, 0) == 0;
 		return regexec(pattern, Pkg.Name(), 0, 0, 0) == 0;
 }
 }
-									/*}}}*/
-bool PackageNameMatchesRegEx::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/
+bool PackageNameMatchesRegEx::operator() (pkgCache::GrpIterator const &Grp) {
 	if (unlikely(pattern == NULL))
 	if (unlikely(pattern == NULL))
 		return false;
 		return false;
 	else
 	else
 		return regexec(pattern, Grp.Name(), 0, 0, 0) == 0;
 		return regexec(pattern, Grp.Name(), 0, 0, 0) == 0;
 }
 }
-									/*}}}*/
-PackageNameMatchesRegEx::~PackageNameMatchesRegEx() {			/*{{{*/
+PackageNameMatchesRegEx::~PackageNameMatchesRegEx() {
 	if (pattern == NULL)
 	if (pattern == NULL)
 		return;
 		return;
 	regfree(pattern);
 	regfree(pattern);
 	delete pattern;
 	delete pattern;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
-// Fnmatch support					/*{{{*/
-//----------------------------------------------------------------------
-bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+// Name matches Fnmatch							/*{{{*/
+PackageNameMatchesFnmatch::PackageNameMatchesFnmatch(std::string const &Pattern) :
+   Pattern(Pattern) {}
+bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {
    return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0;
    return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0;
 }
 }
-									/*}}}*/
-bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/
+bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {
    return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0;
    return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
-// CompleteArch to <kernel>-<cpu> tuple					/*{{{*/
+// Architecture matches <kernel>-<cpu> specification			/*{{{*/
 //----------------------------------------------------------------------
 //----------------------------------------------------------------------
 /* The complete architecture, consisting of <kernel>-<cpu>. */
 /* The complete architecture, consisting of <kernel>-<cpu>. */
 static std::string CompleteArch(std::string const &arch) {
 static std::string CompleteArch(std::string const &arch) {
@@ -82,12 +82,10 @@ static std::string CompleteArch(std::string const &arch) {
 	else if (arch == "any")			return "*-*";
 	else if (arch == "any")			return "*-*";
 	else					return "linux-" + arch;
 	else					return "linux-" + arch;
 }
 }
-									/*}}}*/
-PackageArchitectureMatchesSpecification::PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern) :/*{{{*/
-					literal(pattern), complete(CompleteArch(pattern)), isPattern(isPattern), d(NULL) {
+PackageArchitectureMatchesSpecification::PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern) :
+					literal(pattern), complete(CompleteArch(pattern)), isPattern(isPattern) {
 }
 }
-									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (char const * const &arch) {/*{{{*/
+bool PackageArchitectureMatchesSpecification::operator() (char const * const &arch) {
 	if (strcmp(literal.c_str(), arch) == 0 ||
 	if (strcmp(literal.c_str(), arch) == 0 ||
 	    strcmp(complete.c_str(), arch) == 0)
 	    strcmp(complete.c_str(), arch) == 0)
 		return true;
 		return true;
@@ -96,16 +94,112 @@ bool PackageArchitectureMatchesSpecification::operator() (char const * const &ar
 		return fnmatch(complete.c_str(), pkgarch.c_str(), 0) == 0;
 		return fnmatch(complete.c_str(), pkgarch.c_str(), 0) == 0;
 	return fnmatch(pkgarch.c_str(), complete.c_str(), 0) == 0;
 	return fnmatch(pkgarch.c_str(), complete.c_str(), 0) == 0;
 }
 }
-									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/
+bool PackageArchitectureMatchesSpecification::operator() (pkgCache::PkgIterator const &Pkg) {
 	return (*this)(Pkg.Arch());
 	return (*this)(Pkg.Arch());
+}
+PackageArchitectureMatchesSpecification::~PackageArchitectureMatchesSpecification() {
 }
 }
 									/*}}}*/
 									/*}}}*/
-bool PackageArchitectureMatchesSpecification::operator() (pkgCache::VerIterator const &Ver) {/*{{{*/
-	return (*this)(Ver.ParentPkg());
+// Package is new install						/*{{{*/
+PackageIsNewInstall::PackageIsNewInstall(pkgCacheFile * const Cache) : Cache(Cache) {}
+APT_PURE bool PackageIsNewInstall::operator() (pkgCache::PkgIterator const &Pkg) {
+   return (*Cache)[Pkg].NewInstall();
 }
 }
+PackageIsNewInstall::~PackageIsNewInstall() {}
 									/*}}}*/
 									/*}}}*/
-PackageArchitectureMatchesSpecification::~PackageArchitectureMatchesSpecification() {	/*{{{*/
+// Generica like True, False, NOT, AND, OR				/*{{{*/
+APT_CONST bool TrueMatcher::operator() (pkgCache::PkgIterator const &) { return true; }
+APT_CONST bool TrueMatcher::operator() (pkgCache::GrpIterator const &) { return true; }
+APT_CONST bool TrueMatcher::operator() (pkgCache::VerIterator const &) { return true; }
+
+APT_CONST bool FalseMatcher::operator() (pkgCache::PkgIterator const &) { return false; }
+APT_CONST bool FalseMatcher::operator() (pkgCache::GrpIterator const &) { return false; }
+APT_CONST bool FalseMatcher::operator() (pkgCache::VerIterator const &) { return false; }
+
+NOTMatcher::NOTMatcher(Matcher * const matcher) : matcher(matcher) {}
+bool NOTMatcher::operator() (pkgCache::PkgIterator const &Pkg) { return ! (*matcher)(Pkg); }
+bool NOTMatcher::operator() (pkgCache::GrpIterator const &Grp) { return ! (*matcher)(Grp); }
+bool NOTMatcher::operator() (pkgCache::VerIterator const &Ver) { return ! (*matcher)(Ver); }
+NOTMatcher::~NOTMatcher() { delete matcher; }
+
+ANDMatcher::ANDMatcher() {}
+ANDMatcher::ANDMatcher(Matcher * const matcher1) {
+   AND(matcher1);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2) {
+   AND(matcher1).AND(matcher2);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3) {
+   AND(matcher1).AND(matcher2).AND(matcher3);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4) {
+   AND(matcher1).AND(matcher2).AND(matcher3).AND(matcher4);
+}
+ANDMatcher::ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5) {
+   AND(matcher1).AND(matcher2).AND(matcher3).AND(matcher4).AND(matcher5);
+}
+ANDMatcher& ANDMatcher::AND(Matcher * const matcher) { matchers.push_back(matcher); return *this; }
+bool ANDMatcher::operator() (pkgCache::PkgIterator const &Pkg) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Pkg) == false)
+	 return false;
+   return true;
+}
+bool ANDMatcher::operator() (pkgCache::GrpIterator const &Grp) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Grp) == false)
+	 return false;
+   return true;
+}
+bool ANDMatcher::operator() (pkgCache::VerIterator const &Ver) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Ver) == false)
+	 return false;
+   return true;
+}
+ANDMatcher::~ANDMatcher() {
+   for (std::vector<Matcher *>::iterator M = matchers.begin(); M != matchers.end(); ++M)
+      delete *M;
+}
+
+ORMatcher::ORMatcher() {}
+ORMatcher::ORMatcher(Matcher * const matcher1) {
+   OR(matcher1);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2) {
+   OR(matcher1).OR(matcher2);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3) {
+   OR(matcher1).OR(matcher2).OR(matcher3);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4) {
+   OR(matcher1).OR(matcher2).OR(matcher3).OR(matcher4);
+}
+ORMatcher::ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5) {
+   OR(matcher1).OR(matcher2).OR(matcher3).OR(matcher4).OR(matcher5);
+}
+ORMatcher& ORMatcher::OR(Matcher * const matcher) { matchers.push_back(matcher); return *this; }
+bool ORMatcher::operator() (pkgCache::PkgIterator const &Pkg) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Pkg) == true)
+	 return true;
+   return false;
+}
+bool ORMatcher::operator() (pkgCache::GrpIterator const &Grp) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Grp) == true)
+	 return true;
+   return false;
+}
+bool ORMatcher::operator() (pkgCache::VerIterator const &Ver) {
+   for (std::vector<Matcher *>::const_iterator M = matchers.begin(); M != matchers.end(); ++M)
+      if ((**M)(Ver) == true)
+	 return true;
+   return false;
+}
+ORMatcher::~ORMatcher() {
+   for (std::vector<Matcher *>::iterator M = matchers.begin(); M != matchers.end(); ++M)
+      delete *M;
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

+ 90 - 27
apt-pkg/cachefilter.h

@@ -10,28 +10,90 @@
 #include <apt-pkg/cacheiterators.h>
 #include <apt-pkg/cacheiterators.h>
 
 
 #include <string>
 #include <string>
+#include <vector>
 
 
 #include <regex.h>
 #include <regex.h>
+
+class pkgCacheFile;
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
 
 
-class PackageMatcher {
- public:
-   virtual bool operator() (pkgCache::PkgIterator const &/*Pkg*/) { 
-      return false; };
-   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { 
-      return false; };
-   virtual bool operator() (pkgCache::VerIterator const &/*Ver*/) {
-      return false; };
-   
-   virtual ~PackageMatcher() {};
+class Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &/*Pkg*/) = 0;
+   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) = 0;
+   virtual bool operator() (pkgCache::VerIterator const &/*Ver*/) = 0;
+   virtual ~Matcher();
 };
 };
 
 
-// PackageNameMatchesRegEx						/*{{{*/
-class PackageNameMatchesRegEx : public PackageMatcher {
-         /** \brief dpointer placeholder (for later in case we need it) */
-         void *d;
+class PackageMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg) = 0;
+   virtual bool operator() (pkgCache::VerIterator const &Ver) { return (*this)(Ver.ParentPkg()); }
+   virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { return false; }
+   virtual ~PackageMatcher();
+};
+
+// Generica like True, False, NOT, AND, OR				/*{{{*/
+class TrueMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+};
+
+class FalseMatcher : public Matcher {
+public:
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+};
+
+class NOTMatcher : public Matcher {
+   Matcher * const matcher;
+public:
+   NOTMatcher(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~NOTMatcher();
+};
+
+class ANDMatcher : public Matcher {
+   std::vector<Matcher *> matchers;
+public:
+   // 5 ought to be enough for everybody… c++11 variadic templates would be nice
+   ANDMatcher();
+   ANDMatcher(Matcher * const matcher1);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4);
+   ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5);
+   ANDMatcher& AND(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~ANDMatcher();
+};
+class ORMatcher : public Matcher {
+   std::vector<Matcher *> matchers;
+public:
+   // 5 ought to be enough for everybody… c++11 variadic templates would be nice
+   ORMatcher();
+   ORMatcher(Matcher * const matcher1);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4);
+   ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5);
+   ORMatcher& OR(Matcher * const matcher);
+   virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+   virtual bool operator() (pkgCache::GrpIterator const &Grp);
+   virtual bool operator() (pkgCache::VerIterator const &Ver);
+   virtual ~ORMatcher();
+};
+									/*}}}*/
+class PackageNameMatchesRegEx : public PackageMatcher {			/*{{{*/
 	regex_t* pattern;
 	regex_t* pattern;
 public:
 public:
 	PackageNameMatchesRegEx(std::string const &Pattern);
 	PackageNameMatchesRegEx(std::string const &Pattern);
@@ -40,20 +102,16 @@ public:
 	virtual ~PackageNameMatchesRegEx();
 	virtual ~PackageNameMatchesRegEx();
 };
 };
 									/*}}}*/
 									/*}}}*/
-// PackageNameMatchesFnmatch						/*{{{*/
-   class PackageNameMatchesFnmatch : public PackageMatcher{
-         /** \brief dpointer placeholder (for later in case we need it) */
-         void *d;
-         const std::string Pattern;
+class PackageNameMatchesFnmatch : public PackageMatcher {		/*{{{*/
+	const std::string Pattern;
 public:
 public:
-         PackageNameMatchesFnmatch(std::string const &Pattern) 
-            : Pattern(Pattern) {};
-        virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+	PackageNameMatchesFnmatch(std::string const &Pattern);
+	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
 	virtual bool operator() (pkgCache::GrpIterator const &Grp);
 	virtual bool operator() (pkgCache::GrpIterator const &Grp);
 	virtual ~PackageNameMatchesFnmatch() {};
 	virtual ~PackageNameMatchesFnmatch() {};
 };
 };
 									/*}}}*/
 									/*}}}*/
-// PackageArchitectureMatchesSpecification				/*{{{*/
+class PackageArchitectureMatchesSpecification : public PackageMatcher {	/*{{{*/
 /** \class PackageArchitectureMatchesSpecification
 /** \class PackageArchitectureMatchesSpecification
    \brief matching against architecture specification strings
    \brief matching against architecture specification strings
 
 
@@ -62,12 +120,9 @@ public:
    debian-policy §11.1 "Architecture specification strings".
    debian-policy §11.1 "Architecture specification strings".
 
 
    Examples: i386, mipsel, linux-any, any-amd64, any */
    Examples: i386, mipsel, linux-any, any-amd64, any */
-class PackageArchitectureMatchesSpecification : public PackageMatcher {
 	std::string literal;
 	std::string literal;
 	std::string complete;
 	std::string complete;
 	bool isPattern;
 	bool isPattern;
-	/** \brief dpointer placeholder (for later in case we need it) */
-	void *d;
 public:
 public:
 	/** \brief matching against architecture specification strings
 	/** \brief matching against architecture specification strings
 	 *
 	 *
@@ -79,10 +134,18 @@ public:
 	PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true);
 	PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true);
 	bool operator() (char const * const &arch);
 	bool operator() (char const * const &arch);
 	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
 	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
-	virtual bool operator() (pkgCache::VerIterator const &Ver);
 	virtual ~PackageArchitectureMatchesSpecification();
 	virtual ~PackageArchitectureMatchesSpecification();
 };
 };
 									/*}}}*/
 									/*}}}*/
+class PackageIsNewInstall : public PackageMatcher {			/*{{{*/
+	pkgCacheFile * const Cache;
+public:
+	PackageIsNewInstall(pkgCacheFile * const Cache);
+	virtual bool operator() (pkgCache::PkgIterator const &Pkg);
+	virtual ~PackageIsNewInstall();
+};
+									/*}}}*/
+
 }
 }
 }
 }
 #endif
 #endif