do not pollute namespace in the headers with using (Closes: #500198)
[ntk/apt.git] / apt-pkg / deb / debversion.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
74c1e22b 3// $Id: debversion.cc,v 1.8 2003/09/10 23:39:49 mdz 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
ea542140 14#include <config.h>
b2e465d6
AL
15
16#include <apt-pkg/debversion.h>
17#include <apt-pkg/pkgcache.h>
18
19#include <stdlib.h>
233b185f 20#include <ctype.h>
b2e465d6
AL
21 /*}}}*/
22
23debVersioningSystem debVS;
24
25// debVS::debVersioningSystem - Constructor /*{{{*/
26// ---------------------------------------------------------------------
27/* */
28debVersioningSystem::debVersioningSystem()
29{
30 Label = "Standard .deb";
31}
32 /*}}}*/
1e8167a6 33
b2e465d6
AL
34// debVS::CmpFragment - Compare versions /*{{{*/
35// ---------------------------------------------------------------------
09e712b1
AL
36/* This compares a fragment of the version. This is a slightly adapted
37 version of what dpkg uses. */
38#define order(x) ((x) == '~' ? -1 \
39 : isdigit((x)) ? 0 \
40 : !(x) ? 0 \
41 : isalpha((x)) ? (x) \
42 : (x) + 256)
43int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
b2e465d6
AL
44 const char *B,const char *BEnd)
45{
46 if (A >= AEnd && B >= BEnd)
47 return 0;
48 if (A >= AEnd)
74c1e22b
AL
49 {
50 if (*B == '~') return 1;
b2e465d6 51 return -1;
74c1e22b 52 }
b2e465d6 53 if (B >= BEnd)
74c1e22b
AL
54 {
55 if (*A == '~') return -1;
b2e465d6 56 return 1;
74c1e22b 57 }
09e712b1 58
b2e465d6 59 /* Iterate over the whole string
9373b975 60 What this does is to split the whole string into groups of
b2e465d6
AL
61 numeric and non numeric portions. For instance:
62 a67bhgs89
63 Has 4 portions 'a', '67', 'bhgs', '89'. A more normal:
64 2.7.2-linux-1
65 Has '2', '.', '7', '.' ,'-linux-','1' */
66 const char *lhs = A;
67 const char *rhs = B;
68 while (lhs != AEnd && rhs != BEnd)
69 {
1e8167a6 70 int first_diff = 0;
09e712b1 71
7b464090
AL
72 while (lhs != AEnd && rhs != BEnd &&
73 (!isdigit(*lhs) || !isdigit(*rhs)))
09e712b1
AL
74 {
75 int vc = order(*lhs);
76 int rc = order(*rhs);
77 if (vc != rc)
78 return vc - rc;
1e8167a6 79 lhs++; rhs++;
b2e465d6 80 }
b2e465d6 81
09e712b1
AL
82 while (*lhs == '0')
83 lhs++;
84 while (*rhs == '0')
85 rhs++;
86 while (isdigit(*lhs) && isdigit(*rhs))
87 {
88 if (!first_diff)
89 first_diff = *lhs - *rhs;
90 lhs++;
91 rhs++;
1e8167a6 92 }
09e712b1
AL
93
94 if (isdigit(*lhs))
95 return 1;
96 if (isdigit(*rhs))
97 return -1;
98 if (first_diff)
99 return first_diff;
b2e465d6
AL
100 }
101
102 // The strings must be equal
103 if (lhs == AEnd && rhs == BEnd)
104 return 0;
105
106 // lhs is shorter
107 if (lhs == AEnd)
74c1e22b
AL
108 {
109 if (*rhs == '~') return 1;
b2e465d6 110 return -1;
74c1e22b 111 }
b2e465d6
AL
112
113 // rhs is shorter
114 if (rhs == BEnd)
74c1e22b
AL
115 {
116 if (*lhs == '~') return -1;
b2e465d6 117 return 1;
74c1e22b 118 }
09e712b1 119
b2e465d6
AL
120 // Shouldnt happen
121 return 1;
122}
123 /*}}}*/
124// debVS::CmpVersion - Comparison for versions /*{{{*/
125// ---------------------------------------------------------------------
126/* This fragments the version into E:V-R triples and compares each
127 portion separately. */
128int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd,
129 const char *B,const char *BEnd)
130{
131 // Strip off the epoch and compare it
132 const char *lhs = A;
133 const char *rhs = B;
134 for (;lhs != AEnd && *lhs != ':'; lhs++);
135 for (;rhs != BEnd && *rhs != ':'; rhs++);
136 if (lhs == AEnd)
137 lhs = A;
138 if (rhs == BEnd)
139 rhs = B;
140
9373b975
MV
141 // Special case: a zero epoch is the same as no epoch,
142 // so remove it.
143 if (lhs != A)
144 {
145 for (; *A == '0'; ++A);
146 if (A == lhs)
147 {
148 ++A;
149 ++lhs;
150 }
151 }
152 if (rhs != B)
153 {
154 for (; *B == '0'; ++B);
155 if (B == rhs)
156 {
157 ++B;
158 ++rhs;
159 }
160 }
161
b2e465d6
AL
162 // Compare the epoch
163 int Res = CmpFragment(A,lhs,B,rhs);
164 if (Res != 0)
165 return Res;
166
167 // Skip the :
168 if (lhs != A)
169 lhs++;
170 if (rhs != B)
171 rhs++;
172
173 // Find the last -
174 const char *dlhs = AEnd-1;
175 const char *drhs = BEnd-1;
176 for (;dlhs > lhs && *dlhs != '-'; dlhs--);
177 for (;drhs > rhs && *drhs != '-'; drhs--);
178
179 if (dlhs == lhs)
180 dlhs = AEnd;
181 if (drhs == rhs)
182 drhs = BEnd;
183
184 // Compare the main version
185 Res = CmpFragment(lhs,dlhs,rhs,drhs);
186 if (Res != 0)
187 return Res;
188
189 // Skip the -
190 if (dlhs != lhs)
191 dlhs++;
192 if (drhs != rhs)
193 drhs++;
ea5624c3
DK
194
195 // no debian revision need to be treated like -0
196 if (*(dlhs-1) == '-' && *(drhs-1) == '-')
197 return CmpFragment(dlhs,AEnd,drhs,BEnd);
198 else if (*(dlhs-1) == '-')
199 {
200 const char* null = "0";
201 return CmpFragment(dlhs,AEnd,null, null+1);
202 }
203 else if (*(drhs-1) == '-')
204 {
205 const char* null = "0";
206 return CmpFragment(null, null+1, drhs, BEnd);
207 }
208 else
209 return 0;
b2e465d6
AL
210}
211 /*}}}*/
212// debVS::CheckDep - Check a single dependency /*{{{*/
213// ---------------------------------------------------------------------
214/* This simply preforms the version comparison and switch based on
215 operator. If DepVer is 0 then we are comparing against a provides
216 with no version. */
217bool debVersioningSystem::CheckDep(const char *PkgVer,
218 int Op,const char *DepVer)
219{
220 if (DepVer == 0 || DepVer[0] == 0)
221 return true;
222 if (PkgVer == 0 || PkgVer[0] == 0)
223 return false;
224
225 // Perform the actual comparision.
226 int Res = CmpVersion(PkgVer,DepVer);
227 switch (Op & 0x0F)
228 {
229 case pkgCache::Dep::LessEq:
230 if (Res <= 0)
231 return true;
232 break;
233
234 case pkgCache::Dep::GreaterEq:
235 if (Res >= 0)
236 return true;
237 break;
238
239 case pkgCache::Dep::Less:
240 if (Res < 0)
241 return true;
242 break;
243
244 case pkgCache::Dep::Greater:
245 if (Res > 0)
246 return true;
247 break;
248
249 case pkgCache::Dep::Equals:
250 if (Res == 0)
251 return true;
252 break;
253
254 case pkgCache::Dep::NotEquals:
255 if (Res != 0)
256 return true;
257 break;
258 }
259
260 return false;
261}
262 /*}}}*/
263// debVS::UpstreamVersion - Return the upstream version string /*{{{*/
264// ---------------------------------------------------------------------
265/* This strips all the debian specific information from the version number */
8f3ba4e8 266std::string debVersioningSystem::UpstreamVersion(const char *Ver)
b2e465d6
AL
267{
268 // Strip off the bit before the first colon
269 const char *I = Ver;
270 for (; *I != 0 && *I != ':'; I++);
271 if (*I == ':')
272 Ver = I + 1;
273
274 // Chop off the trailing -
275 I = Ver;
276 unsigned Last = strlen(Ver);
277 for (; *I != 0; I++)
278 if (*I == '-')
279 Last = I - Ver;
280
8f3ba4e8 281 return std::string(Ver,Last);
b2e465d6
AL
282}
283 /*}}}*/