diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-20 23:41:56 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-11-20 23:41:56 +0000 |
commit | b8baf407aacc09167c4e9fa0db55fe323b15854e (patch) | |
tree | e16b83936ea6dcf30e8b9968c5068d03d6bacf55 | |
parent | 9a4c0d59a79efeba4e1c5feed7d07b7c6b6b04ce (diff) | |
download | busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.tar.gz busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.tar.bz2 busybox-w32-b8baf407aacc09167c4e9fa0db55fe323b15854e.zip |
dpkg: better and shorter code to compare versions
(taken from "official" dpkg).
By Eugene T. Bordenkircher (eugebo AT gmail.com)
function old new delta
order - 48 +48
test_version 273 276 +3
version_compare_part 396 187 -209
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 51/-209) Total: -158 bytes
-rw-r--r-- | archival/dpkg.c | 127 |
1 files changed, 59 insertions, 68 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 1bc8d27ce..577b77fec 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -6,6 +6,10 @@ | |||
6 | * written by glenn mcgrath with the help of others | 6 | * written by glenn mcgrath with the help of others |
7 | * copyright (c) 2001 by glenn mcgrath | 7 | * copyright (c) 2001 by glenn mcgrath |
8 | * | 8 | * |
9 | * parts of the version comparison code is plucked from the real dpkg | ||
10 | * application which is licensed GPLv2 and | ||
11 | * copyright (c) 1995 Ian Jackson <ian@chiark.greenend.org.uk> | ||
12 | * | ||
9 | * started life as a busybox implementation of udpkg | 13 | * started life as a busybox implementation of udpkg |
10 | * | 14 | * |
11 | * licensed under gplv2 or later, see file license in this tarball for details. | 15 | * licensed under gplv2 or later, see file license in this tarball for details. |
@@ -135,7 +139,7 @@ static void make_hash(const char *key, unsigned *start, unsigned *decrement, con | |||
135 | /* shifts the ascii based value and adds it to previous value | 139 | /* shifts the ascii based value and adds it to previous value |
136 | * shift amount is mod 24 because long int is 32 bit and data | 140 | * shift amount is mod 24 because long int is 32 bit and data |
137 | * to be shifted is 8, don't want to shift data to where it has | 141 | * to be shifted is 8, don't want to shift data to where it has |
138 | * no effect*/ | 142 | * no effect */ |
139 | hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24); | 143 | hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24); |
140 | } | 144 | } |
141 | *start = (unsigned) hash_num % hash_prime; | 145 | *start = (unsigned) hash_num % hash_prime; |
@@ -183,60 +187,52 @@ static unsigned search_status_hashtable(const char *key) | |||
183 | return probe_address; | 187 | return probe_address; |
184 | } | 188 | } |
185 | 189 | ||
186 | /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */ | 190 | static int order(char x) |
187 | static int version_compare_part(const char *version1, const char *version2) | ||
188 | { | 191 | { |
189 | int upstream_len1 = 0; | 192 | return (x == '~' ? -1 |
190 | int upstream_len2 = 0; | 193 | : x == '\0' ? 0 |
191 | char *name1_char; | 194 | : isdigit(x) ? 0 |
192 | char *name2_char; | 195 | : isalpha(x) ? x |
193 | int len1 = 0; | 196 | : (unsigned char)x + 256 |
194 | int len2 = 0; | 197 | ); |
195 | int tmp_int; | 198 | } |
196 | int ver_num1; | 199 | |
197 | int ver_num2; | 200 | /* This code is taken from dpkg and modified slightly to work with busybox */ |
198 | 201 | static int version_compare_part(const char *val, const char *ref) | |
199 | if (version1 == NULL) { | 202 | { |
200 | version1 = xstrdup(""); | 203 | if (!val) val = ""; |
201 | } | 204 | if (!ref) ref = ""; |
202 | if (version2 == NULL) { | 205 | |
203 | version2 = xstrdup(""); | 206 | while (*val || *ref) { |
204 | } | 207 | int first_diff; |
205 | upstream_len1 = strlen(version1); | 208 | |
206 | upstream_len2 = strlen(version2); | 209 | while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) { |
207 | 210 | int vc = order(*val); | |
208 | while ((len1 < upstream_len1) || (len2 < upstream_len2)) { | 211 | int rc = order(*ref); |
209 | /* Compare non-digit section */ | 212 | if (vc != rc) |
210 | tmp_int = strcspn(&version1[len1], "0123456789"); | 213 | return vc - rc; |
211 | name1_char = xstrndup(&version1[len1], tmp_int); | 214 | val++; |
212 | len1 += tmp_int; | 215 | ref++; |
213 | tmp_int = strcspn(&version2[len2], "0123456789"); | ||
214 | name2_char = xstrndup(&version2[len2], tmp_int); | ||
215 | len2 += tmp_int; | ||
216 | tmp_int = strcmp(name1_char, name2_char); | ||
217 | free(name1_char); | ||
218 | free(name2_char); | ||
219 | if (tmp_int != 0) { | ||
220 | return tmp_int; | ||
221 | } | 216 | } |
222 | 217 | ||
223 | /* Compare digits */ | 218 | while (*val == '0') |
224 | tmp_int = strspn(&version1[len1], "0123456789"); | 219 | val++; |
225 | name1_char = xstrndup(&version1[len1], tmp_int); | 220 | while (*ref == '0') |
226 | len1 += tmp_int; | 221 | ref++; |
227 | tmp_int = strspn(&version2[len2], "0123456789"); | 222 | |
228 | name2_char = xstrndup(&version2[len2], tmp_int); | 223 | first_diff = 0; |
229 | len2 += tmp_int; | 224 | while (isdigit(*val) && isdigit(*ref)) { |
230 | ver_num1 = atoi(name1_char); | 225 | if (first_diff == 0) |
231 | ver_num2 = atoi(name2_char); | 226 | first_diff = *val - *ref; |
232 | free(name1_char); | 227 | val++; |
233 | free(name2_char); | 228 | ref++; |
234 | if (ver_num1 < ver_num2) { | ||
235 | return -1; | ||
236 | } | 229 | } |
237 | if (ver_num1 > ver_num2) { | 230 | if (isdigit(*val)) |
238 | return 1; | 231 | return 1; |
239 | } | 232 | if (isdigit(*ref)) |
233 | return -1; | ||
234 | if (first_diff) | ||
235 | return first_diff; | ||
240 | } | 236 | } |
241 | return 0; | 237 | return 0; |
242 | } | 238 | } |
@@ -249,39 +245,34 @@ static int version_compare(const unsigned ver1, const unsigned ver2) | |||
249 | { | 245 | { |
250 | char *ch_ver1 = name_hashtable[ver1]; | 246 | char *ch_ver1 = name_hashtable[ver1]; |
251 | char *ch_ver2 = name_hashtable[ver2]; | 247 | char *ch_ver2 = name_hashtable[ver2]; |
252 | 248 | unsigned long epoch1 = 0, epoch2 = 0; | |
253 | char epoch1, epoch2; | 249 | char *colon; |
254 | char *deb_ver1, *deb_ver2; | 250 | char *deb_ver1, *deb_ver2; |
255 | char *ver1_ptr, *ver2_ptr; | ||
256 | char *upstream_ver1; | 251 | char *upstream_ver1; |
257 | char *upstream_ver2; | 252 | char *upstream_ver2; |
258 | int result; | 253 | int result; |
259 | 254 | ||
260 | /* Compare epoch */ | 255 | /* Compare epoch */ |
261 | if (ch_ver1[1] == ':') { | 256 | colon = strchr(ch_ver1, ':'); |
262 | epoch1 = ch_ver1[0]; | 257 | if (colon) { |
263 | ver1_ptr = strchr(ch_ver1, ':') + 1; | 258 | epoch1 = atoi(ch_ver1); |
264 | } else { | 259 | ch_ver1 = colon + 1; |
265 | epoch1 = '0'; | ||
266 | ver1_ptr = ch_ver1; | ||
267 | } | 260 | } |
268 | if (ch_ver2[1] == ':') { | 261 | colon = strchr(ch_ver2, ':'); |
269 | epoch2 = ch_ver2[0]; | 262 | if (colon) { |
270 | ver2_ptr = strchr(ch_ver2, ':') + 1; | 263 | epoch2 = atoi(ch_ver2); |
271 | } else { | 264 | ch_ver2 = colon + 1; |
272 | epoch2 = '0'; | ||
273 | ver2_ptr = ch_ver2; | ||
274 | } | 265 | } |
275 | if (epoch1 < epoch2) { | 266 | if (epoch1 < epoch2) { |
276 | return -1; | 267 | return -1; |
277 | } | 268 | } |
278 | else if (epoch1 > epoch2) { | 269 | if (epoch1 > epoch2) { |
279 | return 1; | 270 | return 1; |
280 | } | 271 | } |
281 | 272 | ||
282 | /* Compare upstream version */ | 273 | /* Compare upstream version */ |
283 | upstream_ver1 = xstrdup(ver1_ptr); | 274 | upstream_ver1 = xstrdup(ch_ver1); |
284 | upstream_ver2 = xstrdup(ver2_ptr); | 275 | upstream_ver2 = xstrdup(ch_ver2); |
285 | 276 | ||
286 | /* Chop off debian version, and store for later use */ | 277 | /* Chop off debian version, and store for later use */ |
287 | deb_ver1 = strrchr(upstream_ver1, '-'); | 278 | deb_ver1 = strrchr(upstream_ver1, '-'); |