]> git.saurik.com Git - apt.git/blame - apt-pkg/version.cc
Fixed for new egcs
[apt.git] / apt-pkg / version.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
6fc33863 3// $Id: version.cc,v 1.5 1998/07/19 21:24:18 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 /*}}}*/
56// VersionCompare - Greater than comparison for versions /*{{{*/
57// ---------------------------------------------------------------------
58/* */
59int pkgVersionCompare(const char *A, const char *AEnd, const char *B,
60 const char *BEnd)
61{
62 // lhs = left hand side, rhs = right hand side
63 const char *lhs = A;
64 const char *rhs = B;
65
66 /* Consider epochs. They need special handling because an epoch
67 must not be compared against the first element of the real version.
68 This works okay when both sides have an epoch but when only one
69 does it must compare the missing epoch to 0 */
70 for (;lhs != AEnd && *lhs != ':'; lhs++);
71 for (;rhs != BEnd && *rhs != ':'; rhs++);
72
73 // Parse the epoch out
74 unsigned long lhsEpoch = 0;
75 unsigned long rhsEpoch = 0;
76 if (lhs != AEnd && *lhs == ':')
77 lhsEpoch = StrToLong(A,lhs);
78 if (rhs != BEnd && *rhs == ':')
79 rhsEpoch = StrToLong(B,rhs);
80 if (lhsEpoch != rhsEpoch)
81 {
82 if (lhsEpoch > rhsEpoch)
83 return 1;
84 return -1;
85 }
86
87 /* Iterate over the whole string
88 What this does is to spilt the whole string into groups of
89 numeric and non numeric portions. For instance:
90 a67bhgs89
91 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
92 2.7.2-linux-1
93 Has '2', '.', '7', '.' ,'-linux-','1' */
94 lhs = A;
95 rhs = B;
96 while (lhs != AEnd && rhs != BEnd)
97 {
98 // Starting points
99 const char *Slhs = lhs;
100 const char *Srhs = rhs;
101
102 // Compute ending points were we have passed over the portion
103 bool Digit = (isdigit(*lhs) > 0?true:false);
104 for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
105 for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
106
107 if (Digit == true)
108 {
109 // If the lhs has a digit and the rhs does not then true
110 if (rhs - Srhs == 0)
111 return -1;
112
113 // Generate integers from the strings.
114 unsigned long Ilhs = StrToLong(Slhs,lhs);
115 unsigned long Irhs = StrToLong(Srhs,rhs);
116 if (Ilhs != Irhs)
117 {
118 if (Ilhs > Irhs)
119 return 1;
120 return -1;
121 }
122 }
123 else
124 {
125 // They are equal length so do a straight text compare
126 for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
127 {
128 if (*Slhs != *Srhs)
129 {
130 /* We need to compare non alpha chars as higher than alpha
131 chars (a < !) This is so things like 7.6p2-4 and 7.6-0
132 compare higher as well as . and -. I am not sure how
133 the dpkg code manages to achive the != '-' test, but it
134 is necessary. */
135 int lc = *Slhs;
136 int rc = *Srhs;
137 if (isalpha(lc) == 0 && lc != '-') lc += 256;
138 if (isalpha(rc) == 0 && rc != '-') rc += 256;
139 if (lc > rc)
140 return 1;
141 return -1;
142 }
143 }
144
145 // If the lhs is shorter than the right it is 'less'
146 if (lhs - Slhs < rhs - Srhs)
147 return -1;
148
149 // If the lhs is longer than the right it is 'more'
150 if (lhs - Slhs > rhs - Srhs)
151 return 1;
152 }
153 }
154
155 // The strings must be equal
156 if (lhs == AEnd && rhs == BEnd)
157 return 0;
158
159 // lhs is shorter
160 if (lhs == AEnd)
161 return -1;
162
163 // rhs is shorter
164 if (rhs == BEnd)
165 return 1;
166
167 // Shouldnt happen
168 return 1;
169}
170 /*}}}*/
171// CheckDep - Check a single dependency /*{{{*/
172// ---------------------------------------------------------------------
173/* This simply preforms the version comparison and switch based on
174 operator. */
175bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op)
176{
177 if (DepVer == 0)
178 return true;
179 if (PkgVer == 0)
180 return false;
181
182 // Perform the actuall comparision.
183 int Res = pkgVersionCompare(PkgVer,DepVer);
184 switch (Op & 0x0F)
185 {
6c139d6e 186 case pkgCache::Dep::LessEq:
578bfd0a
AL
187 if (Res <= 0)
188 return true;
189 break;
190
6c139d6e 191 case pkgCache::Dep::GreaterEq:
578bfd0a
AL
192 if (Res >= 0)
193 return true;
194 break;
195
6c139d6e 196 case pkgCache::Dep::Less:
578bfd0a
AL
197 if (Res < 0)
198 return true;
199 break;
200
6c139d6e 201 case pkgCache::Dep::Greater:
578bfd0a
AL
202 if (Res > 0)
203 return true;
204 break;
205
6c139d6e 206 case pkgCache::Dep::Equals:
578bfd0a
AL
207 if (Res == 0)
208 return true;
209 break;
210
6c139d6e 211 case pkgCache::Dep::NotEquals:
578bfd0a
AL
212 if (Res != 0)
213 return true;
214 break;
215 }
216
217 return false;
218}
219 /*}}}*/
220