#include <apt-pkg/debversion.h>
#include <apt-pkg/pkgcache.h>
+#include <string.h>
#include <stdlib.h>
#include <ctype.h>
/*}}}*/
// 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:
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))
return 1;
}
- // Shouldnt happen
+ // Shouldn't happen
return 1;
}
/*}}}*/
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,
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
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)