-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathversion.c
More file actions
159 lines (146 loc) · 4 KB
/
version.c
File metadata and controls
159 lines (146 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "elib.h"
const char * const atom_op_str[] = { "", ">", ">=", "=", "<=", "<", "~", "!", "!!", "*" };
const char * const version_suffixes_str[] = {"alpha", "beta", "pre", "rc", "p", ""};
version_suffixes getsuffix(const char *suff)
{
size_t len = sizeof(version_suffixes_str) / sizeof(*version_suffixes_str);
version_suffixes i;
for (i = 0; i < len; ++i)
if (!strncmp(suff, version_suffixes_str[i],
strlen(version_suffixes_str[i])))
return i;
}
/*
* pms version comparison logic
*/
cmp_code version_cmp(const char *v1, const char *v2)
{
if (!isvalid_version(v1) || !isvalid_version(v2))
return ERROR;
char *ptr1, *ptr2;
unsigned long long n1 = strtoll(v1, &ptr1, 10);
unsigned long long n2 = strtoll(v2, &ptr2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
char c1, c2;
while ((*ptr1 == '.') && (*ptr2 == '.')) {
++ptr1; ++ptr2;
if (*ptr1 == '0' || *ptr2 == '0') {
while (isdigit(*ptr1) || isdigit(*ptr2)) {
c1 = isdigit(*ptr1) ? *ptr1++ : '0';
c2 = isdigit(*ptr2) ? *ptr2++ : '0';
if (c1 > c2)
return 1;
else if (c1 < c2)
return -1;
}
} else {
n1 = strtoll(ptr1, &ptr1, 10);
n2 = strtoll(ptr2, &ptr2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
}
}
if (*ptr1 == '.')
return 1;
else if (*ptr2 == '.')
return -1;
if (isalpha(*ptr1) && isalpha(*ptr2)) {
if (*ptr1 > *ptr2)
return 1;
else if (*ptr1 < *ptr2)
return -1;
++ptr1; ++ptr2;
}
else if (isalpha(*ptr1))
return 1;
else if (isalpha(*ptr2))
return -1;
while ((*ptr1 == '_') && (*ptr2 == '_')) {
++ptr1; ++ptr2;
version_suffixes suff1 = getsuffix(ptr1);
version_suffixes suff2 = getsuffix(ptr2);
if (suff1 > suff2)
return 1;
else if (suff1 < suff2)
return -1;
else {
ptr1 += strlen(version_suffixes_str[suff1]);
ptr2 += strlen(version_suffixes_str[suff2]);
n1 = strtoll(ptr1, &ptr1, 10);
n2 = strtoll(ptr2, &ptr2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
}
}
if (*ptr1 == '_')
return getsuffix(ptr1 + 1) == SUF_P ? 1 : -1;
else if (*ptr2 == '_')
return getsuffix(ptr2 + 1) == SUF_P ? -1 : 1;
n1 = (*ptr1 == '-') ? atoll(ptr1 + 2) : 0;
n2 = (*ptr2 == '-') ? atoll(ptr2 + 2) : 0;
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
return 0;
}
/*
* do versions match according to given operation ?
*/
int version_match(const char *v1, const char *v2, atom_op op)
{
if (!isvalid_version(v1) || !isvalid_version(v2))
return -1;
cmp_code ret = version_cmp(v1, v2);
switch (op) {
case ATOM_OP_NEWER:
return ret == NEWER;
case ATOM_OP_NEWER_EQUAL:
return ret != OLDER;
case ATOM_OP_PV_EQUAL:
case ATOM_OP_EQUAL:
return ret == EQUAL;
case ATOM_OP_OLDER_EQUAL:
return ret != NEWER;
case ATOM_OP_OLDER:
return ret == OLDER;
default:
return 0;
}
}
atom_op atom_op_from_str(const char *op)
{
switch (op[0]) {
case '!':
++op;
if (op[0] == '!')
return ATOM_OP_BLOCK_HARD;
else
return ATOM_OP_BLOCK;
case '>':
++op;
if (op[0] == '=')
return ATOM_OP_NEWER_EQUAL;
else
return ATOM_OP_NEWER;
case '=':
return ATOM_OP_EQUAL;
case '<':
++op;
if (op[0] == '=')
return ATOM_OP_OLDER_EQUAL;
else
return ATOM_OP_OLDER;
case '~':
return ATOM_OP_PV_EQUAL;
default:
return ATOM_OP_NONE;
}
}