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