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