- add evrcmp mode parameter
[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 (s1 == evr1 || *s1 != ':')
102     s1 = 0;
103   if (s2 == evr2 || *s2 != ':')
104     s2 = 0;
105   if (s1 && s2)
106     {
107       r = vercmp(evr1, s1, evr2, s2);
108       if (r)
109         return r;
110       evr1 = s1 + 1;
111       evr2 = s2 + 1;
112     }
113   else if (s1)
114     {
115       if (!pool->promoteepoch)
116         {
117           while (*evr1 == '0')
118             evr1++;
119           if (*evr1 != ':')
120             return 1;
121         }
122       evr1 = s1 + 1;
123     }
124   else if (s2)
125     {
126       while (*evr2 == '0')
127         evr2++;
128       if (*evr2 != ':')
129         return -1;
130       evr2 = s2 + 1;
131     }
132   for (s1 = evr1, r1 = 0; *s1; s1++)
133     if (*s1 == '-')
134       r1 = s1;
135   for (s2 = evr2, r2 = 0; *s2; s2++)
136     if (*s2 == '-')
137       r2 = s2;
138
139   r = 0;
140   if (mode != EVRCMP_MATCH || (evr1 != (r1 ? r1 : s1) && evr2 != (r2 ? r2 : s2)))
141     r = vercmp(evr1, r1 ? r1 : s1, evr2, r2 ? r2 : s2);
142   if (r)
143     return r;
144
145   if (mode == EVRCMP_COMPARE)
146     {
147       if (!r1 && r2)
148         return -1;
149       if (r1 && !r2)
150         return 1;
151     }
152   if (r1 && r2)
153     {
154       if (s1 != ++r1 && s2 != ++r2)
155         r = vercmp(r1, s1, r2, s2);
156     }
157   return r;
158 }
159
160 // EOF