]> git.saurik.com Git - apt.git/blob - apt-pkg/version.cc
Small cosmetic fixes
[apt.git] / apt-pkg / version.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: version.cc,v 1.7 1998/11/28 20:50:24 jgg Exp $
4 /* ######################################################################
5
6 Version - Version string
7
8 Version comparing is done using the == and < operators. STL's
9 function.h provides the remaining set of comparitors. A directly
10 callable non-string class version is provided for functions manipulating
11 the cache file (esp the sort function).
12
13 A version is defined to be equal if a case sensitive compare returns
14 that the two strings are the same. For compatibility with the QSort
15 function this version returns -1,0,1.
16
17 ##################################################################### */
18 /*}}}*/
19 // Include Files /*{{{*/
20 #ifdef __GNUG__
21 #pragma implementation "apt-pkg/version.h"
22 #endif
23
24 #include <apt-pkg/version.h>
25 #include <apt-pkg/pkgcache.h>
26
27 #include <stdlib.h>
28 /*}}}*/
29
30 // StrToLong - Convert the string between two iterators to a long /*{{{*/
31 // ---------------------------------------------------------------------
32 /* */
33 static unsigned long StrToLong(const char *begin,const char *end)
34 {
35 char S[40];
36 char *I = S;
37 for (; begin != end && I < S + 40;)
38 *I++ = *begin++;
39 *I = 0;
40 return strtoul(S,0,10);
41 }
42 /*}}}*/
43 // VersionCompare (op) - Greater than comparison for versions /*{{{*/
44 // ---------------------------------------------------------------------
45 /* */
46 int pkgVersionCompare(const char *A, const char *B)
47 {
48 return pkgVersionCompare(A,A + strlen(A),B,B + strlen(B));
49 }
50 int pkgVersionCompare(string A,string B)
51 {
52 return pkgVersionCompare(A.begin(),A.end(),B.begin(),B.end());
53 }
54
55 /*}}}*/
56 // iVersionCompare - Compare versions /*{{{*/
57 // ---------------------------------------------------------------------
58 /* This compares a fragment of the version. */
59 static int iVersionCompare(const char *A, const char *AEnd, const char *B,
60 const char *BEnd)
61 {
62 // cout << string(A,AEnd) << ',' << string(B,BEnd) << endl;
63 if (A >= AEnd && B >= BEnd)
64 return 0;
65 if (A >= AEnd)
66 return -1;
67 if (B >= BEnd)
68 return 1;
69
70 /* Iterate over the whole string
71 What this does is to spilt the whole string into groups of
72 numeric and non numeric portions. For instance:
73 a67bhgs89
74 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
75 2.7.2-linux-1
76 Has '2', '.', '7', '.' ,'-linux-','1' */
77 const char *lhs = A;
78 const char *rhs = B;
79 while (lhs != AEnd && rhs != BEnd)
80 {
81 // Starting points
82 const char *Slhs = lhs;
83 const char *Srhs = rhs;
84
85 // Compute ending points were we have passed over the portion
86 bool Digit = (isdigit(*lhs) > 0?true:false);
87 for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
88 for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
89
90 if (Digit == true)
91 {
92 // If the lhs has a digit and the rhs does not then <
93 if (rhs - Srhs == 0)
94 return -1;
95
96 // Generate integers from the strings.
97 unsigned long Ilhs = StrToLong(Slhs,lhs);
98 unsigned long Irhs = StrToLong(Srhs,rhs);
99 if (Ilhs != Irhs)
100 {
101 if (Ilhs > Irhs)
102 return 1;
103 return -1;
104 }
105 }
106 else
107 {
108 // They are equal length so do a straight text compare
109 for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
110 {
111 if (*Slhs != *Srhs)
112 {
113 /* We need to compare non alpha chars as higher than alpha
114 chars (a < !) */
115 int lc = *Slhs;
116 int rc = *Srhs;
117 if (isalpha(lc) == 0) lc += 256;
118 if (isalpha(rc) == 0) rc += 256;
119 if (lc > rc)
120 return 1;
121 return -1;
122 }
123 }
124
125 // If the lhs is shorter than the right it is 'less'
126 if (lhs - Slhs < rhs - Srhs)
127 return -1;
128
129 // If the lhs is longer than the right it is 'more'
130 if (lhs - Slhs > rhs - Srhs)
131 return 1;
132 }
133 }
134
135 // The strings must be equal
136 if (lhs == AEnd && rhs == BEnd)
137 return 0;
138
139 // lhs is shorter
140 if (lhs == AEnd)
141 return -1;
142
143 // rhs is shorter
144 if (rhs == BEnd)
145 return 1;
146
147 // Shouldnt happen
148 return 1;
149 }
150 /*}}}*/
151 // VersionCompare - Comparison for versions /*{{{*/
152 // ---------------------------------------------------------------------
153 /* This fragments the version into E:V-R triples and compares each
154 portion seperately. */
155 int pkgVersionCompare(const char *A, const char *AEnd, const char *B,
156 const char *BEnd)
157 {
158 // Strip off the epoch and compare it
159 const char *lhs = A;
160 const char *rhs = B;
161 for (;lhs != AEnd && *lhs != ':'; lhs++);
162 for (;rhs != BEnd && *rhs != ':'; rhs++);
163 if (lhs == AEnd)
164 lhs = A;
165 if (rhs == BEnd)
166 rhs = B;
167
168 // Compare the epoch
169 int Res = iVersionCompare(A,lhs,B,rhs);
170 if (Res != 0)
171 return Res;
172
173 // Skip the :
174 if (lhs != A)
175 lhs++;
176 if (rhs != B)
177 rhs++;
178
179 // Find the last -
180 const char *dlhs = AEnd-1;
181 const char *drhs = BEnd-1;
182 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
183 for (;drhs > rhs && *drhs != '-'; drhs--);
184
185 if (dlhs == A)
186 dlhs = AEnd;
187 if (drhs == B)
188 drhs = BEnd;
189
190 // Compare the main version
191 Res = iVersionCompare(lhs,dlhs,rhs,drhs);
192 if (Res != 0)
193 return Res;
194
195 // Skip the -
196 if (dlhs != lhs)
197 dlhs++;
198 if (drhs != rhs)
199 drhs++;
200 return iVersionCompare(dlhs,AEnd,drhs,BEnd);
201 }
202 /*}}}*/
203 // CheckDep - Check a single dependency /*{{{*/
204 // ---------------------------------------------------------------------
205 /* This simply preforms the version comparison and switch based on
206 operator. */
207 bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op)
208 {
209 if (DepVer == 0)
210 return true;
211 if (PkgVer == 0)
212 return false;
213
214 // Perform the actuall comparision.
215 int Res = pkgVersionCompare(PkgVer,DepVer);
216 switch (Op & 0x0F)
217 {
218 case pkgCache::Dep::LessEq:
219 if (Res <= 0)
220 return true;
221 break;
222
223 case pkgCache::Dep::GreaterEq:
224 if (Res >= 0)
225 return true;
226 break;
227
228 case pkgCache::Dep::Less:
229 if (Res < 0)
230 return true;
231 break;
232
233 case pkgCache::Dep::Greater:
234 if (Res > 0)
235 return true;
236 break;
237
238 case pkgCache::Dep::Equals:
239 if (Res == 0)
240 return true;
241 break;
242
243 case pkgCache::Dep::NotEquals:
244 if (Res != 0)
245 return true;
246 break;
247 }
248
249 return false;
250 }
251 /*}}}*/