]> git.saurik.com Git - apt.git/blob - test/interactive-helper/rpmver.cc
merged lp:~donkult/apt/sid
[apt.git] / test / interactive-helper / rpmver.cc
1 #include <apt-pkg/debversion.h>
2 #include <rpm/rpmio.h>
3 #include <rpm/misc.h>
4 #include <stdlib.h>
5 #include <ctype.h>
6
7 #define xisdigit(x) isdigit(x)
8 #define xisalpha(x) isalpha(x)
9 #define xisalnum(x) (isdigit(x) || isalpha(x))
10
11 using namespace std;
12
13 int rpmvercmp(const char * a, const char * b)
14 {
15 char oldch1, oldch2;
16 char * str1, * str2;
17 char * one, * two;
18 int rc;
19 int isnum;
20
21 /* easy comparison to see if versions are identical */
22 if (!strcmp(a, b)) return 0;
23
24 str1 = (char *)alloca(strlen(a) + 1);
25 str2 = (char *)alloca(strlen(b) + 1);
26
27 strcpy(str1, a);
28 strcpy(str2, b);
29
30 one = str1;
31 two = str2;
32
33 /* loop through each version segment of str1 and str2 and compare them */
34 while (*one && *two) {
35 while (*one && !xisalnum(*one)) one++;
36 while (*two && !xisalnum(*two)) two++;
37
38 str1 = one;
39 str2 = two;
40
41 /* grab first completely alpha or completely numeric segment */
42 /* leave one and two pointing to the start of the alpha or numeric */
43 /* segment and walk str1 and str2 to end of segment */
44 if (xisdigit(*str1)) {
45 while (*str1 && xisdigit(*str1)) str1++;
46 while (*str2 && xisdigit(*str2)) str2++;
47 isnum = 1;
48 } else {
49 while (*str1 && xisalpha(*str1)) str1++;
50 while (*str2 && xisalpha(*str2)) str2++;
51 isnum = 0;
52 }
53
54 /* save character at the end of the alpha or numeric segment */
55 /* so that they can be restored after the comparison */
56 oldch1 = *str1;
57 *str1 = '\0';
58 oldch2 = *str2;
59 *str2 = '\0';
60
61 /* take care of the case where the two version segments are */
62 /* different types: one numeric, the other alpha (i.e. empty) */
63 if (one == str1) return -1; /* arbitrary */
64 if (two == str2) return 1;
65
66 if (isnum) {
67 /* this used to be done by converting the digit segments */
68 /* to ints using atoi() - it's changed because long */
69 /* digit segments can overflow an int - this should fix that. */
70
71 /* throw away any leading zeros - it's a number, right? */
72 while (*one == '0') one++;
73 while (*two == '0') two++;
74
75 /* whichever number has more digits wins */
76 if (strlen(one) > strlen(two)) return 1;
77 if (strlen(two) > strlen(one)) return -1;
78 }
79
80 /* strcmp will return which one is greater - even if the two */
81 /* segments are alpha or if they are numeric. don't return */
82 /* if they are equal because there might be more segments to */
83 /* compare */
84 rc = strcmp(one, two);
85 if (rc) return rc;
86
87 /* restore character that was replaced by null above */
88 *str1 = oldch1;
89 one = str1;
90 *str2 = oldch2;
91 two = str2;
92 }
93
94 /* this catches the case where all numeric and alpha segments have */
95 /* compared identically but the segment sepparating characters were */
96 /* different */
97 if ((!*one) && (!*two)) return 0;
98
99 /* whichever version still has characters left over wins */
100 if (!*one) return -1; else return 1;
101 }
102
103 int main(int argc,const char *argv[])
104 {
105 printf("%i\n",strcmp(argv[1],argv[2]));
106
107 printf("'%s' <> '%s': ",argv[1],argv[2]);
108 printf("rpm: %i deb: %i\n",rpmvercmp(argv[1],argv[2]),
109 debVS.CmpFragment(argv[1],argv[1]+strlen(argv[1]),
110 argv[2],argv[2]+strlen(argv[2])));
111
112 printf("'%s' <> '%s': ",argv[2],argv[1]);
113 printf("rpm: %i deb: %i\n",rpmvercmp(argv[2],argv[1]),
114 debVS.CmpFragment(argv[2],argv[2]+strlen(argv[2]),
115 argv[1],argv[1]+strlen(argv[1])));
116 return 0;
117 }