// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: debversion.cc,v 1.7 2003/07/18 14:13:59 mdz Exp $
+// $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz Exp $
/* ######################################################################
Debian Version - Versioning system for Debian
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#define APT_COMPATIBILITY 986
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debversion.h"
-#endif
+#include <config.h>
#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)
+ else if (isalpha(c))
+ return c;
+ else if (c == '~')
return -1;
- if (B >= BEnd)
- 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 spilt the whole string into groups of
+ What this does is to split the whole string into groups of
numeric and non numeric portions. For instance:
a67bhgs89
Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
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))
// lhs is shorter
if (lhs == AEnd)
+ {
+ if (*rhs == '~') return 1;
return -1;
+ }
// rhs is shorter
if (rhs == BEnd)
+ {
+ if (*lhs == '~') return -1;
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,
+ // so remove it.
+ if (lhs != A)
+ {
+ for (; *A == '0'; ++A);
+ if (A == lhs)
+ {
+ ++A;
+ ++lhs;
+ }
+ }
+ if (rhs != B)
+ {
+ for (; *B == '0'; ++B);
+ if (B == rhs)
+ {
+ ++B;
+ ++rhs;
+ }
+ }
+
// Compare the epoch
int Res = CmpFragment(A,lhs,B,rhs);
if (Res != 0)
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
dlhs++;
if (drhs != rhs)
drhs++;
-
- return CmpFragment(dlhs,AEnd,drhs,BEnd);
+
+ // no debian revision need to be treated like -0
+ if (*(dlhs-1) == '-' && *(drhs-1) == '-')
+ return CmpFragment(dlhs,AEnd,drhs,BEnd);
+ else if (*(dlhs-1) == '-')
+ {
+ const char* null = "0";
+ return CmpFragment(dlhs,AEnd,null, null+1);
+ }
+ else if (*(drhs-1) == '-')
+ {
+ const char* null = "0";
+ return CmpFragment(null, null+1, drhs, BEnd);
+ }
+ else
+ return 0;
}
/*}}}*/
// debVS::CheckDep - Check a single dependency /*{{{*/
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)
// debVS::UpstreamVersion - Return the upstream version string /*{{{*/
// ---------------------------------------------------------------------
/* This strips all the debian specific information from the version number */
-string debVersioningSystem::UpstreamVersion(const char *Ver)
+std::string debVersioningSystem::UpstreamVersion(const char *Ver)
{
// Strip off the bit before the first colon
const char *I = Ver;
if (*I == '-')
Last = I - Ver;
- return string(Ver,Last);
+ return std::string(Ver,Last);
}
/*}}}*/