]> git.saurik.com Git - apt.git/blame - apt-pkg/version.cc
Fixed extraneous showing of [working]
[apt.git] / apt-pkg / version.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
6a19558e 3// $Id: version.cc,v 1.7 1998/11/28 20:50:24 jgg Exp $
578bfd0a
AL
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 /*{{{*/
6c139d6e 20#ifdef __GNUG__
094a497d 21#pragma implementation "apt-pkg/version.h"
6c139d6e
AL
22#endif
23
094a497d
AL
24#include <apt-pkg/version.h>
25#include <apt-pkg/pkgcache.h>
578bfd0a
AL
26
27#include <stdlib.h>
28 /*}}}*/
29
578bfd0a
AL
30// StrToLong - Convert the string between two iterators to a long /*{{{*/
31// ---------------------------------------------------------------------
32/* */
33static 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/* */
46int pkgVersionCompare(const char *A, const char *B)
47{
48 return pkgVersionCompare(A,A + strlen(A),B,B + strlen(B));
49}
50int pkgVersionCompare(string A,string B)
51{
52 return pkgVersionCompare(A.begin(),A.end(),B.begin(),B.end());
53}
54
55 /*}}}*/
1e4e52e0 56// iVersionCompare - Compare versions /*{{{*/
578bfd0a 57// ---------------------------------------------------------------------
1e4e52e0
AL
58/* This compares a fragment of the version. */
59static int iVersionCompare(const char *A, const char *AEnd, const char *B,
60 const char *BEnd)
578bfd0a 61{
6a19558e 62 // cout << string(A,AEnd) << ',' << string(B,BEnd) << endl;
1e4e52e0
AL
63 if (A >= AEnd && B >= BEnd)
64 return 0;
65 if (A >= AEnd)
578bfd0a 66 return -1;
1e4e52e0
AL
67 if (B >= BEnd)
68 return 1;
578bfd0a
AL
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' */
1e4e52e0
AL
77 const char *lhs = A;
78 const char *rhs = B;
578bfd0a
AL
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 {
1e4e52e0 92 // If the lhs has a digit and the rhs does not then <
578bfd0a
AL
93 if (rhs - Srhs == 0)
94 return -1;
1e4e52e0 95
578bfd0a
AL
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
1e4e52e0 114 chars (a < !) */
578bfd0a
AL
115 int lc = *Slhs;
116 int rc = *Srhs;
1e4e52e0
AL
117 if (isalpha(lc) == 0) lc += 256;
118 if (isalpha(rc) == 0) rc += 256;
578bfd0a
AL
119 if (lc > rc)
120 return 1;
121 return -1;
122 }
123 }
1e4e52e0 124
578bfd0a
AL
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 /*}}}*/
1e4e52e0
AL
151// VersionCompare - Comparison for versions /*{{{*/
152// ---------------------------------------------------------------------
153/* This fragments the version into E:V-R triples and compares each
154 portion seperately. */
155int 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--);
6a19558e
AL
184
185 if (dlhs == A)
186 dlhs = AEnd;
187 if (drhs == B)
188 drhs = BEnd;
1e4e52e0
AL
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 /*}}}*/
578bfd0a
AL
203// CheckDep - Check a single dependency /*{{{*/
204// ---------------------------------------------------------------------
205/* This simply preforms the version comparison and switch based on
206 operator. */
207bool 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 {
6c139d6e 218 case pkgCache::Dep::LessEq:
578bfd0a
AL
219 if (Res <= 0)
220 return true;
221 break;
222
6c139d6e 223 case pkgCache::Dep::GreaterEq:
578bfd0a
AL
224 if (Res >= 0)
225 return true;
226 break;
227
6c139d6e 228 case pkgCache::Dep::Less:
578bfd0a
AL
229 if (Res < 0)
230 return true;
231 break;
232
6c139d6e 233 case pkgCache::Dep::Greater:
578bfd0a
AL
234 if (Res > 0)
235 return true;
236 break;
237
6c139d6e 238 case pkgCache::Dep::Equals:
578bfd0a
AL
239 if (Res == 0)
240 return true;
241 break;
242
6c139d6e 243 case pkgCache::Dep::NotEquals:
578bfd0a
AL
244 if (Res != 0)
245 return true;
246 break;
247 }
248
249 return false;
250}
251 /*}}}*/