X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/1bc6873583b01469f4981d738f4d0d4132ccfdbf..8d0d92558c00d1825e413ce67be51a46a5c18aea:/apt-pkg/deb/debversion.cc

diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc
index bc9e13d92..48462c6a2 100644
--- a/apt-pkg/deb/debversion.cc
+++ b/apt-pkg/deb/debversion.cc
@@ -15,6 +15,7 @@
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/pkgcache.h>
 
+#include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 									/*}}}*/
@@ -32,29 +33,26 @@ debVersioningSystem::debVersioningSystem()
 
 // debVS::CmpFragment - Compare versions			        /*{{{*/
 // ---------------------------------------------------------------------
-/* This compares a fragment of the version. This is a slightly adapted 
-   version of what dpkg uses. */
-#define order(x) ((x) == '~' ? -1    \
-		: isdigit((x)) ? 0   \
-		: !(x) ? 0           \
-		: isalpha((x)) ? (x) \
-		: (x) + 256)
-int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
-				     const char *B,const char *BEnd)
+/* This compares a fragment of the version. This is a slightly adapted
+   version of what dpkg uses in dpkg/lib/dpkg/version.c.
+   In particular, the a | b = NULL check is removed as we check this in the
+   caller, we use an explicit end for a | b strings and we check ~ explicit. */
+static int order(char c)
 {
-   if (A >= AEnd && B >= BEnd)
+   if (isdigit(c))
       return 0;
-   if (A >= AEnd)
-   {
-      if (*B == '~') return 1;
+   else if (isalpha(c))
+      return c;
+   else if (c == '~')
       return -1;
-   }
-   if (B >= BEnd)
-   {
-      if (*A == '~') return -1;
-      return 1;
-   }
-
+   else if (c)
+      return c + 256;
+   else
+      return 0;
+}
+int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
+				     const char *B,const char *BEnd)
+{
    /* Iterate over the whole string
       What this does is to split the whole string into groups of
       numeric and non numeric portions. For instance:
@@ -75,19 +73,19 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
 	 int rc = order(*rhs);
 	 if (vc != rc)
 	    return vc - rc;
-	 lhs++; rhs++;
+	 ++lhs; ++rhs;
       }
 
       while (*lhs == '0')
-	 lhs++;
+	 ++lhs;
       while (*rhs == '0')
-	 rhs++;
+	 ++rhs;
       while (isdigit(*lhs) && isdigit(*rhs))
       {
 	 if (!first_diff)
 	    first_diff = *lhs - *rhs;
-	 lhs++;
-	 rhs++;
+	 ++lhs;
+	 ++rhs;
       }
 
       if (isdigit(*lhs))
@@ -116,7 +114,7 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
       return 1;
    }
 
-   // Shouldnt happen
+   // Shouldn't happen
    return 1;
 }
 									/*}}}*/
@@ -127,14 +125,12 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
 int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
 				      const char *B,const char *BEnd)
 {
-   // Strip off the epoch and compare it 
-   const char *lhs = A;
-   const char *rhs = B;
-   for (;lhs != AEnd && *lhs != ':'; lhs++);
-   for (;rhs != BEnd && *rhs != ':'; rhs++);
-   if (lhs == AEnd)
+   // Strip off the epoch and compare it
+   const char *lhs = (const char*) memchr(A, ':', AEnd - A);
+   const char *rhs = (const char*) memchr(B, ':', BEnd - B);
+   if (lhs == NULL)
       lhs = A;
-   if (rhs == BEnd)
+   if (rhs == NULL)
       rhs = B;
    
    // Special case: a zero epoch is the same as no epoch,
@@ -169,15 +165,12 @@ int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
    if (rhs != B)
       rhs++;
    
-   // Find the last - 
-   const char *dlhs = AEnd-1;
-   const char *drhs = BEnd-1;
-   for (;dlhs > lhs && *dlhs != '-'; dlhs--);
-   for (;drhs > rhs && *drhs != '-'; drhs--);
-
-   if (dlhs == lhs)
+   // Find the last -
+   const char *dlhs = (const char*) memrchr(lhs, '-', AEnd - lhs);
+   const char *drhs = (const char*) memrchr(rhs, '-', BEnd - rhs);
+   if (dlhs == NULL)
       dlhs = AEnd;
-   if (drhs == rhs)
+   if (drhs == NULL)
       drhs = BEnd;
    
    // Compare the main version
@@ -220,10 +213,15 @@ bool debVersioningSystem::CheckDep(const char *PkgVer,
       return true;
    if (PkgVer == 0 || PkgVer[0] == 0)
       return false;
-   
-   // Perform the actual comparision.
-   int Res = CmpVersion(PkgVer,DepVer);
-   switch (Op & 0x0F)
+   Op &= 0x0F;
+
+   // fast track for (equal) strings [by location] which are by definition equal versions
+   if (PkgVer == DepVer)
+      return Op == pkgCache::Dep::Equals || Op == pkgCache::Dep::LessEq || Op == pkgCache::Dep::GreaterEq;
+
+   // Perform the actual comparison.
+   int const Res = CmpVersion(PkgVer, DepVer);
+   switch (Op)
    {
       case pkgCache::Dep::LessEq:
       if (Res <= 0)