G++3 fixes from Randolph
[ntk/apt.git] / apt-pkg / deb / debversion.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
233b185f 3// $Id: debversion.cc,v 1.3 2001/05/07 05:14:53 jgg Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Debian Version - Versioning system for Debian
7
8 This implements the standard Debian versioning system.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
13#define APT_COMPATIBILITY 986
14#ifdef __GNUG__
15#pragma implementation "apt-pkg/debversion.h"
16#endif
17
18#include <apt-pkg/debversion.h>
19#include <apt-pkg/pkgcache.h>
20
21#include <stdlib.h>
233b185f 22#include <ctype.h>
b2e465d6
AL
23 /*}}}*/
24
25debVersioningSystem debVS;
26
27// debVS::debVersioningSystem - Constructor /*{{{*/
28// ---------------------------------------------------------------------
29/* */
30debVersioningSystem::debVersioningSystem()
31{
32 Label = "Standard .deb";
33}
34 /*}}}*/
35// StrToLong - Convert the string between two iterators to a long /*{{{*/
36// ---------------------------------------------------------------------
37/* */
38static unsigned long StrToLong(const char *begin,const char *end)
39{
40 char S[40];
41 char *I = S;
42 for (; begin != end && I < S + 40;)
43 *I++ = *begin++;
44 *I = 0;
45 return strtoul(S,0,10);
46}
47 /*}}}*/
48// debVS::CmpFragment - Compare versions /*{{{*/
49// ---------------------------------------------------------------------
50/* This compares a fragment of the version. Dpkg has a really short
51 version of this, but it is uh.. interesting to grok. */
52int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
53 const char *B,const char *BEnd)
54{
55 if (A >= AEnd && B >= BEnd)
56 return 0;
57 if (A >= AEnd)
58 return -1;
59 if (B >= BEnd)
60 return 1;
61
62 /* Iterate over the whole string
63 What this does is to spilt the whole string into groups of
64 numeric and non numeric portions. For instance:
65 a67bhgs89
66 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
67 2.7.2-linux-1
68 Has '2', '.', '7', '.' ,'-linux-','1' */
69 const char *lhs = A;
70 const char *rhs = B;
71 while (lhs != AEnd && rhs != BEnd)
72 {
73 // Starting points
74 const char *Slhs = lhs;
75 const char *Srhs = rhs;
76
77 // Compute ending points were we have passed over the portion
78 bool Digit = (isdigit(*lhs) > 0?true:false);
79 for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++);
80 for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++);
81
82 if (Digit == true)
83 {
84 // If the lhs has a digit and the rhs does not then <
85 if (rhs - Srhs == 0)
86 return -1;
87
88 // Generate integers from the strings.
89 unsigned long Ilhs = StrToLong(Slhs,lhs);
90 unsigned long Irhs = StrToLong(Srhs,rhs);
91 if (Ilhs != Irhs)
92 {
93 if (Ilhs > Irhs)
94 return 1;
95 return -1;
96 }
97 }
98 else
99 {
100 // They are equal length so do a straight text compare
101 for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++)
102 {
103 if (*Slhs != *Srhs)
104 {
105 /* We need to compare non alpha chars as higher than alpha
106 chars (a < !) */
107 int lc = *Slhs;
108 int rc = *Srhs;
109 if (isalpha(lc) == 0) lc += 256;
110 if (isalpha(rc) == 0) rc += 256;
111 if (lc > rc)
112 return 1;
113 return -1;
114 }
115 }
116
117 // If the lhs is shorter than the right it is 'less'
118 if (lhs - Slhs < rhs - Srhs)
119 return -1;
120
121 // If the lhs is longer than the right it is 'more'
122 if (lhs - Slhs > rhs - Srhs)
123 return 1;
124 }
125 }
126
127 // The strings must be equal
128 if (lhs == AEnd && rhs == BEnd)
129 return 0;
130
131 // lhs is shorter
132 if (lhs == AEnd)
133 return -1;
134
135 // rhs is shorter
136 if (rhs == BEnd)
137 return 1;
138
139 // Shouldnt happen
140 return 1;
141}
142 /*}}}*/
143// debVS::CmpVersion - Comparison for versions /*{{{*/
144// ---------------------------------------------------------------------
145/* This fragments the version into E:V-R triples and compares each
146 portion separately. */
147int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
148 const char *B,const char *BEnd)
149{
150 // Strip off the epoch and compare it
151 const char *lhs = A;
152 const char *rhs = B;
153 for (;lhs != AEnd && *lhs != ':'; lhs++);
154 for (;rhs != BEnd && *rhs != ':'; rhs++);
155 if (lhs == AEnd)
156 lhs = A;
157 if (rhs == BEnd)
158 rhs = B;
159
160 // Compare the epoch
161 int Res = CmpFragment(A,lhs,B,rhs);
162 if (Res != 0)
163 return Res;
164
165 // Skip the :
166 if (lhs != A)
167 lhs++;
168 if (rhs != B)
169 rhs++;
170
171 // Find the last -
172 const char *dlhs = AEnd-1;
173 const char *drhs = BEnd-1;
174 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
175 for (;drhs > rhs && *drhs != '-'; drhs--);
176
177 if (dlhs == lhs)
178 dlhs = AEnd;
179 if (drhs == rhs)
180 drhs = BEnd;
181
182 // Compare the main version
183 Res = CmpFragment(lhs,dlhs,rhs,drhs);
184 if (Res != 0)
185 return Res;
186
187 // Skip the -
188 if (dlhs != lhs)
189 dlhs++;
190 if (drhs != rhs)
191 drhs++;
192
193 return CmpFragment(dlhs,AEnd,drhs,BEnd);
194}
195 /*}}}*/
196// debVS::CheckDep - Check a single dependency /*{{{*/
197// ---------------------------------------------------------------------
198/* This simply preforms the version comparison and switch based on
199 operator. If DepVer is 0 then we are comparing against a provides
200 with no version. */
201bool debVersioningSystem::CheckDep(const char *PkgVer,
202 int Op,const char *DepVer)
203{
204 if (DepVer == 0 || DepVer[0] == 0)
205 return true;
206 if (PkgVer == 0 || PkgVer[0] == 0)
207 return false;
208
209 // Perform the actual comparision.
210 int Res = CmpVersion(PkgVer,DepVer);
211 switch (Op & 0x0F)
212 {
213 case pkgCache::Dep::LessEq:
214 if (Res <= 0)
215 return true;
216 break;
217
218 case pkgCache::Dep::GreaterEq:
219 if (Res >= 0)
220 return true;
221 break;
222
223 case pkgCache::Dep::Less:
224 if (Res < 0)
225 return true;
226 break;
227
228 case pkgCache::Dep::Greater:
229 if (Res > 0)
230 return true;
231 break;
232
233 case pkgCache::Dep::Equals:
234 if (Res == 0)
235 return true;
236 break;
237
238 case pkgCache::Dep::NotEquals:
239 if (Res != 0)
240 return true;
241 break;
242 }
243
244 return false;
245}
246 /*}}}*/
247// debVS::UpstreamVersion - Return the upstream version string /*{{{*/
248// ---------------------------------------------------------------------
249/* This strips all the debian specific information from the version number */
250string debVersioningSystem::UpstreamVersion(const char *Ver)
251{
252 // Strip off the bit before the first colon
253 const char *I = Ver;
254 for (; *I != 0 && *I != ':'; I++);
255 if (*I == ':')
256 Ver = I + 1;
257
258 // Chop off the trailing -
259 I = Ver;
260 unsigned Last = strlen(Ver);
261 for (; *I != 0; I++)
262 if (*I == '-')
263 Last = I - Ver;
264
265 return string(Ver,Last);
266}
267 /*}}}*/