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