Fixed or handling bug
[ntk/apt.git] / apt-pkg / version.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
fb0ee66e 3// $Id: version.cc,v 1.9 1999/04/19 06:03:09 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{
1e4e52e0
AL
62 if (A >= AEnd && B >= BEnd)
63 return 0;
64 if (A >= AEnd)
578bfd0a 65 return -1;
1e4e52e0
AL
66 if (B >= BEnd)
67 return 1;
578bfd0a
AL
68
69 /* Iterate over the whole string
70 What this does is to spilt the whole string into groups of
71 numeric and non numeric portions. For instance:
72 a67bhgs89
73 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
74 2.7.2-linux-1
75 Has '2', '.', '7', '.' ,'-linux-','1' */
1e4e52e0
AL
76 const char *lhs = A;
77 const char *rhs = B;
578bfd0a
AL
78 while (lhs != AEnd && rhs != BEnd)
79 {
80 // Starting points
81 const char *Slhs = lhs;
82 const char *Srhs = rhs;
83
84 // Compute ending points were we have passed over the portion
85 bool Digit = (isdigit(*lhs) > 0?true:false);
86 for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
87 for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
88
89 if (Digit == true)
90 {
1e4e52e0 91 // If the lhs has a digit and the rhs does not then <
578bfd0a
AL
92 if (rhs - Srhs == 0)
93 return -1;
1e4e52e0 94
578bfd0a
AL
95 // Generate integers from the strings.
96 unsigned long Ilhs = StrToLong(Slhs,lhs);
97 unsigned long Irhs = StrToLong(Srhs,rhs);
98 if (Ilhs != Irhs)
99 {
100 if (Ilhs > Irhs)
101 return 1;
102 return -1;
103 }
104 }
105 else
106 {
107 // They are equal length so do a straight text compare
108 for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
109 {
110 if (*Slhs != *Srhs)
111 {
112 /* We need to compare non alpha chars as higher than alpha
1e4e52e0 113 chars (a < !) */
578bfd0a
AL
114 int lc = *Slhs;
115 int rc = *Srhs;
1e4e52e0
AL
116 if (isalpha(lc) == 0) lc += 256;
117 if (isalpha(rc) == 0) rc += 256;
578bfd0a
AL
118 if (lc > rc)
119 return 1;
120 return -1;
121 }
122 }
1e4e52e0 123
578bfd0a
AL
124 // If the lhs is shorter than the right it is 'less'
125 if (lhs - Slhs < rhs - Srhs)
126 return -1;
127
128 // If the lhs is longer than the right it is 'more'
129 if (lhs - Slhs > rhs - Srhs)
130 return 1;
131 }
132 }
133
134 // The strings must be equal
135 if (lhs == AEnd && rhs == BEnd)
136 return 0;
137
138 // lhs is shorter
139 if (lhs == AEnd)
140 return -1;
141
142 // rhs is shorter
143 if (rhs == BEnd)
144 return 1;
145
146 // Shouldnt happen
147 return 1;
148}
149 /*}}}*/
1e4e52e0
AL
150// VersionCompare - Comparison for versions /*{{{*/
151// ---------------------------------------------------------------------
152/* This fragments the version into E:V-R triples and compares each
153 portion seperately. */
154int pkgVersionCompare(const char *A, const char *AEnd, const char *B,
155 const char *BEnd)
156{
157 // Strip off the epoch and compare it
158 const char *lhs = A;
159 const char *rhs = B;
160 for (;lhs != AEnd && *lhs != ':'; lhs++);
161 for (;rhs != BEnd && *rhs != ':'; rhs++);
162 if (lhs == AEnd)
163 lhs = A;
164 if (rhs == BEnd)
165 rhs = B;
166
167 // Compare the epoch
168 int Res = iVersionCompare(A,lhs,B,rhs);
169 if (Res != 0)
170 return Res;
171
172 // Skip the :
173 if (lhs != A)
174 lhs++;
175 if (rhs != B)
176 rhs++;
177
178 // Find the last -
179 const char *dlhs = AEnd-1;
180 const char *drhs = BEnd-1;
181 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
182 for (;drhs > rhs && *drhs != '-'; drhs--);
6a19558e 183
143e0a1f 184 if (dlhs == lhs)
6a19558e 185 dlhs = AEnd;
143e0a1f 186 if (drhs == rhs)
6a19558e 187 drhs = BEnd;
1e4e52e0
AL
188
189 // Compare the main version
190 Res = iVersionCompare(lhs,dlhs,rhs,drhs);
191 if (Res != 0)
192 return Res;
193
194 // Skip the -
195 if (dlhs != lhs)
196 dlhs++;
197 if (drhs != rhs)
198 drhs++;
199 return iVersionCompare(dlhs,AEnd,drhs,BEnd);
200}
201 /*}}}*/
578bfd0a
AL
202// CheckDep - Check a single dependency /*{{{*/
203// ---------------------------------------------------------------------
204/* This simply preforms the version comparison and switch based on
205 operator. */
206bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op)
207{
208 if (DepVer == 0)
209 return true;
210 if (PkgVer == 0)
211 return false;
212
213 // Perform the actuall comparision.
214 int Res = pkgVersionCompare(PkgVer,DepVer);
215 switch (Op & 0x0F)
216 {
6c139d6e 217 case pkgCache::Dep::LessEq:
578bfd0a
AL
218 if (Res <= 0)
219 return true;
220 break;
221
6c139d6e 222 case pkgCache::Dep::GreaterEq:
578bfd0a
AL
223 if (Res >= 0)
224 return true;
225 break;
226
6c139d6e 227 case pkgCache::Dep::Less:
578bfd0a
AL
228 if (Res < 0)
229 return true;
230 break;
231
6c139d6e 232 case pkgCache::Dep::Greater:
578bfd0a
AL
233 if (Res > 0)
234 return true;
235 break;
236
6c139d6e 237 case pkgCache::Dep::Equals:
578bfd0a
AL
238 if (Res == 0)
239 return true;
240 break;
241
6c139d6e 242 case pkgCache::Dep::NotEquals:
578bfd0a
AL
243 if (Res != 0)
244 return true;
245 break;
246 }
247
248 return false;
249}
250 /*}}}*/
fb0ee66e
AL
251// BaseVersion - Return the upstream version string /*{{{*/
252// ---------------------------------------------------------------------
253/* This strips all the debian specific information from the version number */
254string pkgBaseVersion(const char *Ver)
255{
256 // Strip off the bit before the first colon
257 const char *I = Ver;
258 for (; *I != 0 && *I != ':'; I++);
259 if (*I == ':')
260 Ver = I + 1;
261
262 // Chop off the trailing -
263 I = Ver;
264 unsigned Last = strlen(Ver);
265 for (; *I != 0; I++)
266 if (*I == '-')
267 Last = I - Ver;
268
269 return string(Ver,Last);
270}
271 /*}}}*/