Merge branch 'master' of gitorious.org:opensuse/sat-solver
[platform/upstream/libsolv.git] / src / evr.c
1 /*
2  * Copyright (c) 2007-2009, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * evr.c
10  *
11  * version compare
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include "evr.h"
17 #include "pool.h"
18
19
20
21 #if defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
22
23 #ifdef MULTI_SEMANTICS
24 # define vercmp vercmp_deb
25 #endif
26
27 /* debian type version compare */
28 int
29 vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
30 {
31   int r, c1, c2;
32   while (1)
33     {
34       c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
35       c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
36       if ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
37         {
38           while (c1 == '0')
39             c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
40           while (c2 == '0')
41             c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
42           r = 0;
43           while ((c1 >= '0' && c1 <= '9') && (c2 >= '0' && c2 <= '9'))
44             {
45               if (!r)
46                 r = c1 - c2;
47               c1 = s1 < q1 ? *(const unsigned char *)s1++ : 0;
48               c2 = s2 < q2 ? *(const unsigned char *)s2++ : 0;
49             }
50           if (c1 >= '0' && c1 <= '9')
51             return 1;
52           if (c2 >= '0' && c2 <= '9')
53             return -1;
54           if (r)
55             return r < 0 ? -1 : 1;
56         }
57       c1 = c1 == '~' ? -1 : !c1 || (c1 >= '0' && c1 <= '9') || (c1 >= 'A' && c1 <= 'Z') || (c1 >= 'a' && c1 <= 'z')  ? c1 : c1 + 256;
58       c2 = c2 == '~' ? -1 : !c2 || (c2 >= '0' && c2 <= '9') || (c2 >= 'A' && c2 <= 'Z') || (c2 >= 'a' && c2 <= 'z')  ? c2 : c2 + 256;
59       r = c1 - c2;
60       if (r)
61         return r < 0 ? -1 : 1;
62       if (!c1)
63         return 0;
64     }
65 }
66
67 #ifdef MULTI_SEMANTICS
68 # undef vercmp
69 #endif
70
71 #endif
72
73 #if !defined(DEBIAN_SEMANTICS) || defined(MULTI_SEMANTICS)
74
75 /* rpm type version compare */
76 int
77 vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
78 {
79   int r = 0;
80   const char *e1, *e2;
81
82   while (s1 < q1 && s2 < q2)
83     {
84       while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') &&
85           !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z'))
86         s1++;
87       while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') &&
88           !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z'))
89         s2++;
90       if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9'))
91         {
92           while (*s1 == '0' && s1[1] >= '0' && s1[1] <= '9')
93             s1++;
94           while (*s2 == '0' && s2[1] >= '0' && s2[1] <= '9')
95             s2++;
96           for (e1 = s1; *e1 >= '0' && *e1 <= '9'; )
97             e1++;
98           for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
99             e2++;
100           r = e1 - s1 - (e2 - s2);
101           if (!r)
102             r = strncmp(s1, s2, e1 - s1);
103           if (r)
104             return r > 0 ? 1 : -1;
105         }
106       else
107         {
108           for (e1 = s1; (*e1 >= 'a' && *e1 <= 'z') || (*e1 >= 'A' && *e1 <= 'Z'); )
109             e1++;
110           for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
111             e2++;
112           r = e1 - s1 - (e2 - s2);
113           if (r > 0)
114             {
115               r = strncmp(s1, s2, e2 - s2);
116               return r >= 0 ? 1 : -1;
117             }
118           if (r < 0)
119             {
120               r = strncmp(s1, s2, e1 - s1);
121               return r <= 0 ? -1 : 1;
122             }
123           r = strncmp(s1, s2, e1 - s1);
124           if (r)
125             return r > 0 ? 1 : -1;
126         }
127       s1 = e1;
128       s2 = e2;
129     }
130   return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
131 }
132
133 #endif
134
135 #if defined(MULTI_SEMANTICS)
136 # define vercmp (*(pool->disttype == DISTTYPE_DEB ? &vercmp_deb : &ver##cmp))
137 #endif
138
139 /* edition (e:v-r) compare */
140 int
141 evrcmp_str(const Pool *pool, const char *evr1, const char *evr2, int mode)
142 {
143   int r;
144   const char *s1, *s2;
145   const char *r1, *r2;
146
147   if (evr1 == evr2)
148     return 0;
149
150 #if 0
151   POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s mode=%d\n", evr1, evr2, mode);
152 #endif
153   for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
154     ;
155   for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
156     ;
157   if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
158     {
159       /* empty epoch, skip epoch check */
160       if (*s1 == ':')
161         evr1 = s1 + 1;
162       if (*s2 == ':')
163         evr2 = s2 + 1;
164       s1 = evr1;
165       s2 = evr2;
166     }
167   if (s1 == evr1 || *s1 != ':')
168     s1 = 0;
169   if (s2 == evr2 || *s2 != ':')
170     s2 = 0;
171   if (s1 && s2)
172     {
173       r = vercmp(evr1, s1, evr2, s2);
174       if (r)
175         return r;
176       evr1 = s1 + 1;
177       evr2 = s2 + 1;
178     }
179   else if (s1)
180     {
181       if (!pool->promoteepoch)
182         {
183           while (*evr1 == '0')
184             evr1++;
185           if (*evr1 != ':')
186             return 1;
187         }
188       evr1 = s1 + 1;
189     }
190   else if (s2)
191     {
192       while (*evr2 == '0')
193         evr2++;
194       if (*evr2 != ':')
195         return -1;
196       evr2 = s2 + 1;
197     }
198   for (s1 = evr1, r1 = 0; *s1; s1++)
199     if (*s1 == '-')
200       r1 = s1;
201   for (s2 = evr2, r2 = 0; *s2; s2++)
202     if (*s2 == '-')
203       r2 = s2;
204
205   r = 0;
206   if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
207     r = vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
208   if (r)
209     return r;
210
211   if (mode == EVRCMP_COMPARE)
212     {
213       if (!r1 && r2)
214         return -1;
215       if (r1 && !r2)
216         return 1;
217     }
218   if (mode == EVRCMP_COMPARE_EVONLY)
219     return 0;
220   if (r1 && r2)
221     {
222       if (s1 != ++r1 && s2 != ++r2)
223         r = vercmp(r1, s1, r2, s2);
224     }
225   return r;
226 }
227
228 int
229 evrcmp(const Pool *pool, Id evr1id, Id evr2id, int mode)
230 {
231   const char *evr1, *evr2;
232   if (evr1id == evr2id)
233     return 0;
234   evr1 = id2str(pool, evr1id);
235   evr2 = id2str(pool, evr2id);
236   return evrcmp_str(pool, evr1, evr2, mode);
237 }
238
239 int
240 evrmatch(const Pool *pool, Id evrid, const char *epoch, const char *version, const char *release)
241 {
242   const char *evr1;
243   const char *s1;
244   const char *r1;
245   int r;
246
247   evr1 = id2str(pool, evrid);
248   for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
249     ;
250   if (s1 != evr1 && *s1 == ':')
251     {
252       if (epoch)
253         {
254           r = vercmp(evr1, s1, epoch, epoch + strlen(epoch));
255           if (r)
256             return r;
257         }
258       evr1 = s1 + 1;
259     }
260   else if (epoch)
261     {
262       while (*epoch == '0')
263         epoch++;
264       if (*epoch)
265         return -1;
266     }
267   for (s1 = evr1, r1 = 0; *s1; s1++)
268     if (*s1 == '-')
269       r1 = s1;
270   if (version)
271     {
272       r = vercmp(evr1, r1 ? r1 : s1, version, version + strlen(version));
273       if (r)
274         return r;
275     }
276   if (release)
277     {
278       if (!r1)
279         return -1;
280       r = vercmp(r1 + 1, s1, release, release + strlen(release));
281       if (r)
282         return r;
283     }
284   return 0;
285 }
286
287 // EOF