Skip to content

Instantly share code, notes, and snippets.

@fajran
Created November 25, 2008 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fajran/28868 to your computer and use it in GitHub Desktop.
Save fajran/28868 to your computer and use it in GitHub Desktop.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/*}}}*/
#define order(x) ((x) == '~' ? -1 \
: isdigit((x)) ? 0 \
: !(x) ? 0 \
: isalpha((x)) ? (x) \
: (x) + 256)
int 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 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:
2.7.2-linux-1
Has '2', '.', '7', '.' ,'-linux-','1' */
const char *lhs = A;
const char *rhs = B;
while (lhs != AEnd && rhs != BEnd)
{
int first_diff = 0;
while (lhs != AEnd && rhs != BEnd &&
(!isdigit(*lhs) || !isdigit(*rhs)))
{
int vc = order(*lhs);
int rc = order(*rhs);
if (vc != rc)
return vc - rc;
lhs++; rhs++;
}
while (*lhs == '0')
lhs++;
while (*rhs == '0')
rhs++;
while (isdigit(*lhs) && isdigit(*rhs))
{
if (!first_diff)
first_diff = *lhs - *rhs;
lhs++;
rhs++;
}
if (isdigit(*lhs))
return 1;
if (isdigit(*rhs))
return -1;
if (first_diff)
return first_diff;
}
// The strings must be equal
if (lhs == AEnd && rhs == BEnd)
return 0;
// 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;
}
/*}}}*/
// debVS::CmpVersion - Comparison for versions /*{{{*/
// ---------------------------------------------------------------------
/* This fragments the version into E:V-R triples and compares each
portion separately. */
int 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)
lhs = A;
if (rhs == BEnd)
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)
return Res;
// Skip the :
if (lhs != A)
lhs++;
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)
dlhs = AEnd;
if (drhs == rhs)
drhs = BEnd;
// Compare the main version
Res = CmpFragment(lhs,dlhs,rhs,drhs);
if (Res != 0)
return Res;
// Skip the -
if (dlhs != lhs)
dlhs++;
if (drhs != rhs)
drhs++;
return CmpFragment(dlhs,AEnd,drhs,BEnd);
}
/*}}}*/
int main(int argc, char** argv) {
char *satu = argv[1];
char *dua = argv[2];
char *satuend = &satu[strlen(satu)];
char *duaend = &dua[strlen(dua)];
int cmp;
printf("%s vs %s = ", satu, dua);
cmp = DoCmpVersion(satu, satuend, dua, duaend);
if (cmp < 0) {
printf("lebih kecil\n");
}
else if (cmp > 0) {
printf("lebih besar\n");
}
else {
printf("sama\n");
}
}
all : debversion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment