- add evrmatch
[platform/upstream/libsolv.git] / src / evr.c
1 /*
2  * Copyright (c) 2007, 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 int
20 vercmp(const char *s1, const char *q1, const char *s2, const char *q2)
21 {
22   int r = 0;
23   const char *e1, *e2;
24
25   while (s1 < q1 && s2 < q2)
26     {
27       while (s1 < q1 && !(*s1 >= '0' && *s1 <= '9') &&
28           !(*s1 >= 'a' && *s1 <= 'z') && !(*s1 >= 'A' && *s1 <= 'Z'))
29         s1++;
30       while (s2 < q2 && !(*s2 >= '0' && *s2 <= '9') &&
31           !(*s2 >= 'a' && *s2 <= 'z') && !(*s2 >= 'A' && *s2 <= 'Z'))
32         s2++;
33       if ((*s1 >= '0' && *s1 <= '9') || (*s2 >= '0' && *s2 <= '9'))
34         {
35           while (*s1 == '0' && s1[1] >= '0' && s1[1] <= '9')
36             s1++;
37           while (*s2 == '0' && s2[1] >= '0' && s2[1] <= '9')
38             s2++;
39           for (e1 = s1; *e1 >= '0' && *e1 <= '9'; )
40             e1++;
41           for (e2 = s2; *e2 >= '0' && *e2 <= '9'; )
42             e2++;
43           r = e1 - s1 - (e2 - s2);
44           if (!r)
45             r = strncmp(s1, s2, e1 - s1);
46           if (r)
47             return r > 0 ? 1 : -1;
48         }
49       else
50         {
51           for (e1 = s1; (*e1 >= 'a' && *e1 <= 'z') || (*e1 >= 'A' && *e1 <= 'Z'); )
52             e1++;
53           for (e2 = s2; (*e2 >= 'a' && *e2 <= 'z') || (*e2 >= 'A' && *e2 <= 'Z'); )
54             e2++;
55           r = e1 - s1 - (e2 - s2);
56           if (r > 0)
57             {
58               r = strncmp(s1, s2, e2 - s2);
59               return r >= 0 ? 1 : -1;
60             }
61           if (r < 0)
62             {
63               r = strncmp(s1, s2, e1 - s1);
64               return r <= 0 ? -1 : 1;
65             }
66           r = strncmp(s1, s2, e1 - s1);
67           if (r)
68             return r > 0 ? 1 : -1;
69         }
70       s1 = e1;
71       s2 = e2;
72     }
73   return s1 < q1 ? 1 : s2 < q2 ? -1 : 0;
74 }
75
76 #define EVRCMP_COMPARE                  0
77 #define EVRCMP_MATCH_RELEASE            1
78 #define EVRCMP_MATCH                    2
79
80 // edition (e:v-r) compare
81 int
82 evrcmp(Pool *pool, Id evr1id, Id evr2id, int mode)
83 {
84   int r;
85   const char *evr1, *evr2;
86   const char *s1, *s2;
87   const char *r1, *r2;
88
89   if (evr1id == evr2id)
90     return 0;
91   evr1 = id2str(pool, evr1id);
92   evr2 = id2str(pool, evr2id);
93
94 #if 0
95   POOL_DEBUG(DEBUG_EVRCMP, "evrcmp %s %s mode=%d\n", evr1, evr2, mode);
96 #endif
97   for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
98     ;
99   for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
100     ;
101   if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
102     {
103       /* empty epoch, skip epoch check */
104       if (*s1 == ':')
105         evr1 = s1 + 1;
106       if (*s2 == ':')
107         evr2 = s2 + 1;
108       s1 = evr1;
109       s2 = evr2;
110     }
111   if (s1 == evr1 || *s1 != ':')
112     s1 = 0;
113   if (s2 == evr2 || *s2 != ':')
114     s2 = 0;
115   if (s1 && s2)
116     {
117       r = vercmp(evr1, s1, evr2, s2);
118       if (r)
119         return r;
120       evr1 = s1 + 1;
121       evr2 = s2 + 1;
122     }
123   else if (s1)
124     {
125       if (!pool->promoteepoch)
126         {
127           while (*evr1 == '0')
128             evr1++;
129           if (*evr1 != ':')
130             return 1;
131         }
132       evr1 = s1 + 1;
133     }
134   else if (s2)
135     {
136       while (*evr2 == '0')
137         evr2++;
138       if (*evr2 != ':')
139         return -1;
140       evr2 = s2 + 1;
141     }
142   for (s1 = evr1, r1 = 0; *s1; s1++)
143     if (*s1 == '-')
144       r1 = s1;
145   for (s2 = evr2, r2 = 0; *s2; s2++)
146     if (*s2 == '-')
147       r2 = s2;
148
149   r = 0;
150   if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
151     r = vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
152   if (r)
153     return r;
154
155   if (mode == EVRCMP_COMPARE)
156     {
157       if (!r1 && r2)
158         return -1;
159       if (r1 && !r2)
160         return 1;
161     }
162   if (r1 && r2)
163     {
164       if (s1 != ++r1 && s2 != ++r2)
165         r = vercmp(r1, s1, r2, s2);
166     }
167   return r;
168 }
169
170 int
171 evrmatch(Pool *pool, Id evrid, const char *epoch, const char *version, const char *release)
172 {
173   const char *evr1;
174   const char *s1;
175   const char *r1;
176   int r;
177
178   evr1 = id2str(pool, evrid);
179   for (s1 = evr1; *s1 >= '0' && *s1 <= '9'; s1++)
180     ;
181   if (s1 != evr1 && *s1 == ':')
182     {
183       if (epoch)
184         {
185           r = vercmp(evr1, s1, epoch, epoch + strlen(epoch));
186           if (r)
187             return r;
188         }
189       evr1 = s1 + 1;
190     }
191   else if (epoch)
192     {
193       while (*epoch == '0')
194         epoch++;
195       if (*epoch)
196         return -1;
197     }
198   for (s1 = evr1, r1 = 0; *s1; s1++)
199     if (*s1 == '-')
200       r1 = s1;
201   if (version)
202     {
203       r = vercmp(evr1, r1 ? r1 : s1, version, version + strlen(version));
204       if (r)
205         return r;
206     }
207   if (release)
208     {
209       if (!r1)
210         return -1;
211       r = vercmp(r1 + 1, s1, release, release + strlen(release));
212       if (r)
213         return r;
214     }
215   return 0;
216 }
217
218 // EOF