]> git.saurik.com Git - apt.git/blame - apt-pkg/version.cc
Tuning
[apt.git] / apt-pkg / version.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
094a497d 3// $Id: version.cc,v 1.4 1998/07/12 23:58:42 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
30// Version::pkgVersion - Default Constructor /*{{{*/
31// ---------------------------------------------------------------------
32/* */
33pkgVersion::pkgVersion()
34{
35}
36 /*}}}*/
37// Version::operator == - Checks if two versions are equal /*{{{*/
38// ---------------------------------------------------------------------
39/* We can't simply perform a string compare because of epochs. */
40bool pkgVersion::operator ==(const pkgVersion &Vrhs) const
41{
42 if (pkgVersionCompare(Value.begin(),Value.end(),
43 Vrhs.Value.begin(),Vrhs.Value.end()) == 0)
44 return true;
45 return false;
46}
47 /*}}}*/
48// Version::operator < - Checks if this is less than another version /*{{{*/
49// ---------------------------------------------------------------------
50/* All other forms of comparision can be built up from this single function.
51 a > b -> b < a
52 a <= b -> !(a > b) -> !(b < a)
53 a >= b -> !(a < b)
54 */
55bool pkgVersion::operator <(const pkgVersion &Vrhs) const
56{
57 if (pkgVersionCompare(Value.begin(),Value.end(),
58 Vrhs.Value.begin(),Vrhs.Value.end()) == -1)
59 return true;
60 return false;
61}
62 /*}}}*/
63// StrToLong - Convert the string between two iterators to a long /*{{{*/
64// ---------------------------------------------------------------------
65/* */
66static unsigned long StrToLong(const char *begin,const char *end)
67{
68 char S[40];
69 char *I = S;
70 for (; begin != end && I < S + 40;)
71 *I++ = *begin++;
72 *I = 0;
73 return strtoul(S,0,10);
74}
75 /*}}}*/
76// VersionCompare (op) - Greater than comparison for versions /*{{{*/
77// ---------------------------------------------------------------------
78/* */
79int pkgVersionCompare(const char *A, const char *B)
80{
81 return pkgVersionCompare(A,A + strlen(A),B,B + strlen(B));
82}
83int pkgVersionCompare(string A,string B)
84{
85 return pkgVersionCompare(A.begin(),A.end(),B.begin(),B.end());
86}
87
88 /*}}}*/
89// VersionCompare - Greater than comparison for versions /*{{{*/
90// ---------------------------------------------------------------------
91/* */
92int pkgVersionCompare(const char *A, const char *AEnd, const char *B,
93 const char *BEnd)
94{
95 // lhs = left hand side, rhs = right hand side
96 const char *lhs = A;
97 const char *rhs = B;
98
99 /* Consider epochs. They need special handling because an epoch
100 must not be compared against the first element of the real version.
101 This works okay when both sides have an epoch but when only one
102 does it must compare the missing epoch to 0 */
103 for (;lhs != AEnd && *lhs != ':'; lhs++);
104 for (;rhs != BEnd && *rhs != ':'; rhs++);
105
106 // Parse the epoch out
107 unsigned long lhsEpoch = 0;
108 unsigned long rhsEpoch = 0;
109 if (lhs != AEnd && *lhs == ':')
110 lhsEpoch = StrToLong(A,lhs);
111 if (rhs != BEnd && *rhs == ':')
112 rhsEpoch = StrToLong(B,rhs);
113 if (lhsEpoch != rhsEpoch)
114 {
115 if (lhsEpoch > rhsEpoch)
116 return 1;
117 return -1;
118 }
119
120 /* Iterate over the whole string
121 What this does is to spilt the whole string into groups of
122 numeric and non numeric portions. For instance:
123 a67bhgs89
124 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
125 2.7.2-linux-1
126 Has '2', '.', '7', '.' ,'-linux-','1' */
127 lhs = A;
128 rhs = B;
129 while (lhs != AEnd && rhs != BEnd)
130 {
131 // Starting points
132 const char *Slhs = lhs;
133 const char *Srhs = rhs;
134
135 // Compute ending points were we have passed over the portion
136 bool Digit = (isdigit(*lhs) > 0?true:false);
137 for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
138 for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
139
140 if (Digit == true)
141 {
142 // If the lhs has a digit and the rhs does not then true
143 if (rhs - Srhs == 0)
144 return -1;
145
146 // Generate integers from the strings.
147 unsigned long Ilhs = StrToLong(Slhs,lhs);
148 unsigned long Irhs = StrToLong(Srhs,rhs);
149 if (Ilhs != Irhs)
150 {
151 if (Ilhs > Irhs)
152 return 1;
153 return -1;
154 }
155 }
156 else
157 {
158 // They are equal length so do a straight text compare
159 for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
160 {
161 if (*Slhs != *Srhs)
162 {
163 /* We need to compare non alpha chars as higher than alpha
164 chars (a < !) This is so things like 7.6p2-4 and 7.6-0
165 compare higher as well as . and -. I am not sure how
166 the dpkg code manages to achive the != '-' test, but it
167 is necessary. */
168 int lc = *Slhs;
169 int rc = *Srhs;
170 if (isalpha(lc) == 0 && lc != '-') lc += 256;
171 if (isalpha(rc) == 0 && rc != '-') rc += 256;
172 if (lc > rc)
173 return 1;
174 return -1;
175 }
176 }
177
178 // If the lhs is shorter than the right it is 'less'
179 if (lhs - Slhs < rhs - Srhs)
180 return -1;
181
182 // If the lhs is longer than the right it is 'more'
183 if (lhs - Slhs > rhs - Srhs)
184 return 1;
185 }
186 }
187
188 // The strings must be equal
189 if (lhs == AEnd && rhs == BEnd)
190 return 0;
191
192 // lhs is shorter
193 if (lhs == AEnd)
194 return -1;
195
196 // rhs is shorter
197 if (rhs == BEnd)
198 return 1;
199
200 // Shouldnt happen
201 return 1;
202}
203 /*}}}*/
204// CheckDep - Check a single dependency /*{{{*/
205// ---------------------------------------------------------------------
206/* This simply preforms the version comparison and switch based on
207 operator. */
208bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op)
209{
210 if (DepVer == 0)
211 return true;
212 if (PkgVer == 0)
213 return false;
214
215 // Perform the actuall comparision.
216 int Res = pkgVersionCompare(PkgVer,DepVer);
217 switch (Op & 0x0F)
218 {
6c139d6e 219 case pkgCache::Dep::LessEq:
578bfd0a
AL
220 if (Res <= 0)
221 return true;
222 break;
223
6c139d6e 224 case pkgCache::Dep::GreaterEq:
578bfd0a
AL
225 if (Res >= 0)
226 return true;
227 break;
228
6c139d6e 229 case pkgCache::Dep::Less:
578bfd0a
AL
230 if (Res < 0)
231 return true;
232 break;
233
6c139d6e 234 case pkgCache::Dep::Greater:
578bfd0a
AL
235 if (Res > 0)
236 return true;
237 break;
238
6c139d6e 239 case pkgCache::Dep::Equals:
578bfd0a
AL
240 if (Res == 0)
241 return true;
242 break;
243
6c139d6e 244 case pkgCache::Dep::NotEquals:
578bfd0a
AL
245 if (Res != 0)
246 return true;
247 break;
248 }
249
250 return false;
251}
252 /*}}}*/
253