Skip to content

Instantly share code, notes, and snippets.

@fajran
Created January 19, 2009 22:13
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/49204 to your computer and use it in GitHub Desktop.
Save fajran/49204 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;
}
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--);
// --->8--- hapus pada nanggar+1 --->8---
// Modifikasi #2: Geser batas revisi satu fragmen ke kiri
if (!getenv ("BLANKON_UBUNTU_MODE"))
{
if (dlhs < AEnd && strstr(dlhs, "blankon") && strstr(dlhs, "+blankon") == 0)
for (dlhs--; dlhs > lhs && *dlhs != '-'; dlhs--);
if (drhs < BEnd && strstr(drhs, "blankon") && strstr(drhs, "+blankon") == 0)
for (drhs--; drhs > rhs && *drhs != '-'; drhs--);
}
// ---------------------------------->8--
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++;
if (getenv ("BLANKON_UBUNTU_MODE"))
return CmpFragment(dlhs,AEnd,drhs,BEnd);
if (dlhs >= AEnd && drhs >= BEnd)
return 0;
if (dlhs >= AEnd)
{
if (*drhs == '~') return 1;
return -1;
}
if (drhs >= BEnd)
{
if (*dlhs == '~') return -1;
return 1;
}
// Modifikasi #3 dan #4 (konvensi baru)
if (strstr (dlhs, "+blankon") && strstr (drhs, "+blankon") == 0)
return 1;
if (strstr (drhs, "+blankon") && strstr (dlhs, "+blankon") == 0)
return -1;
// --->8--- hapus pada nanggar+1 --->8---
// Modifikasi #4 (konvensi lama)
if (strstr (dlhs, "blankon") && strstr (drhs, "blankon") == 0)
return 1;
if (strstr (drhs, "blankon") && strstr (dlhs, "blankon") == 0)
return -1;
// ---------------------------------->8--
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");
return 0;
}
else if (cmp > 0) {
printf("lebih besar\n");
return 2;
}
else {
printf("sama\n");
return 1;
}
}
all : debversion
test : all
./runtest.sh
#!/bin/bash
INPUT=testcases.txt
DEBVERSION=./debversion
passcnt=0
failcnt=0
faillist=""
grep -v '^\s*#' -v $INPUT | grep -v '^\s*$' | while read a b c
do
$DEBVERSION "$a" "$b" > /dev/null
ret=$?
val=$(( ret - 1 ))
if [ "$val" -eq "$c" ]; then
echo "pass"
else
echo "fail: $a vs $b => $val (expected: $c)"
fi
done
# Format penulisan
#
# versi-satu SP versi-dua SP hasil-harapan
#
# SP = spasi
# hasil-harapan = -1, 0, 1 = lebih kecil, sama, lebih besar
# normal
0.1 0.1 0
0.1 0.2 -1
0.2 0.1 1
0.1-1 0.1-1 0
0.1-1 0.1-2 -1
0.1-2 0.1-1 1
0.2-1 0.1-2 1
0.1-2 0.2-1 -1
# menang dari ubuntu
1.2-3ubuntu4 1.2-3ubuntu4-0blankon1 -1
1.3-3ubuntu4 1.2-3ubuntu4-0blankon1 1
1.2-3ubuntu5 1.2-3ubuntu4-0blankon1 -1
1.2-3ubuntu4 1.2-3ubuntu4+blankon5 -1
1.2-3ubuntu5 1.2-3ubuntu4+blankon5 -1
1.3-3ubuntu5 1.2-3ubuntu4+blankon5 1
# transisi konvensi
1.2-3ubuntu4-0blankon1 1.2-3ubuntu4+blankon1 -1
0.1-1.2 0.1-1.2-1blankon2 -1
0.1-1.2 0.1-1.2+blankon2 -1
1-0blankon1-0blankon1 1 1
1-0blankon1-0blankon1+blankon1 1-0blankon1-0blankon1-0blankon1 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment