X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b2e465d6d32d2dc884f58b94acb7e35f671a87fe..1b7bf822ad9504f6d01cd4422d830e8815143912:/apt-pkg/deb/debversion.cc diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc index e7c42fd11..140561262 100644 --- a/apt-pkg/deb/debversion.cc +++ b/apt-pkg/deb/debversion.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debversion.cc,v 1.2 2001/02/20 07:03:17 jgg Exp $ +// $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz Exp $ /* ###################################################################### Debian Version - Versioning system for Debian @@ -10,15 +10,13 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#define APT_COMPATIBILITY 986 -#ifdef __GNUG__ -#pragma implementation "apt-pkg/debversion.h" -#endif +#include #include #include #include +#include /*}}}*/ debVersioningSystem debVS; @@ -31,35 +29,34 @@ debVersioningSystem::debVersioningSystem() Label = "Standard .deb"; } /*}}}*/ -// StrToLong - Convert the string between two iterators to a long /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static unsigned long StrToLong(const char *begin,const char *end) -{ - char S[40]; - char *I = S; - for (; begin != end && I < S + 40;) - *I++ = *begin++; - *I = 0; - return strtoul(S,0,10); -} - /*}}}*/ + // debVS::CmpFragment - Compare versions /*{{{*/ // --------------------------------------------------------------------- -/* This compares a fragment of the version. Dpkg has a really short - version of this, but it is uh.. interesting to grok. */ -int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, +/* 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) { if (A >= AEnd && B >= BEnd) return 0; if (A >= AEnd) + { + if (*B == '~') return 1; return -1; + } if (B >= BEnd) + { + if (*A == '~') return -1; return 1; - + } + /* 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: @@ -69,58 +66,36 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, const char *rhs = B; while (lhs != AEnd && rhs != BEnd) { - // Starting points - const char *Slhs = lhs; - const char *Srhs = rhs; - - // Compute ending points were we have passed over the portion - bool Digit = (isdigit(*lhs) > 0?true:false); - for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++); - for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++); - - if (Digit == true) + int first_diff = 0; + + while (lhs != AEnd && rhs != BEnd && + (!isdigit(*lhs) || !isdigit(*rhs))) { - // If the lhs has a digit and the rhs does not then < - if (rhs - Srhs == 0) - return -1; - - // Generate integers from the strings. - unsigned long Ilhs = StrToLong(Slhs,lhs); - unsigned long Irhs = StrToLong(Srhs,rhs); - if (Ilhs != Irhs) - { - if (Ilhs > Irhs) - return 1; - return -1; - } + int vc = order(*lhs); + int rc = order(*rhs); + if (vc != rc) + return vc - rc; + lhs++; rhs++; } - else - { - // They are equal length so do a straight text compare - for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++) - { - if (*Slhs != *Srhs) - { - /* We need to compare non alpha chars as higher than alpha - chars (a < !) */ - int lc = *Slhs; - int rc = *Srhs; - if (isalpha(lc) == 0) lc += 256; - if (isalpha(rc) == 0) rc += 256; - if (lc > rc) - return 1; - return -1; - } - } - // If the lhs is shorter than the right it is 'less' - if (lhs - Slhs < rhs - Srhs) - return -1; + while (*lhs == '0') + lhs++; + while (*rhs == '0') + rhs++; + while (isdigit(*lhs) && isdigit(*rhs)) + { + if (!first_diff) + first_diff = *lhs - *rhs; + lhs++; + rhs++; + } - // If the lhs is longer than the right it is 'more' - if (lhs - Slhs > rhs - Srhs) - return 1; - } + if (isdigit(*lhs)) + return 1; + if (isdigit(*rhs)) + return -1; + if (first_diff) + return first_diff; } // The strings must be equal @@ -129,12 +104,18 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, // 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 return 1; } @@ -146,16 +127,35 @@ 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, + // 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) @@ -167,15 +167,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 @@ -188,8 +185,22 @@ int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd, 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 /*{{{*/ @@ -204,10 +215,15 @@ bool debVersioningSystem::CheckDep(const char *PkgVer, return true; if (PkgVer == 0 || PkgVer[0] == 0) return false; - + 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 comparision. - int Res = CmpVersion(PkgVer,DepVer); - switch (Op & 0x0F) + int const Res = CmpVersion(PkgVer, DepVer); + switch (Op) { case pkgCache::Dep::LessEq: if (Res <= 0) @@ -246,7 +262,7 @@ bool debVersioningSystem::CheckDep(const char *PkgVer, // 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; @@ -261,6 +277,6 @@ string debVersioningSystem::UpstreamVersion(const char *Ver) if (*I == '-') Last = I - Ver; - return string(Ver,Last); + return std::string(Ver,Last); } /*}}}*/