From 7e26842094e3335424fcbf792b09807d806d1cf2 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Tue, 26 Jul 2011 11:56:59 -0500 Subject: [PATCH] pkg: add pkg_compare_version() --- pkg.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pkg.h | 4 +++ 2 files changed, 113 insertions(+) diff --git a/pkg.c b/pkg.c index 806230f..63eddb5 100644 --- a/pkg.c +++ b/pkg.c @@ -33,6 +33,115 @@ pkg_find(const char *name) return parse_file(locbuf); } +/* + * pkg_compare_version(a, b) + * + * compare versions using RPM version comparison rules as described in the LSB. + */ +int +pkg_compare_version(const char *a, const char *b) +{ + char oldch1, oldch2; + char *str1, *str2; + char *one, *two; + int ret; + bool isnum; + + /* optimization: if version matches then it's the same version. */ + if (!strcasecmp(a, b)) + return 0; + + str1 = LOCAL_COPY(a); + str2 = LOCAL_COPY(b); + + one = str1; + two = str2; + + while (*one && *two) + { + while (*one && !isalnum(*one)) + one++; + while (*two && !isalnum(*two)) + one++; + + if (!(*one && *two)) + break; + + str1 = one; + str2 = two; + + if (isdigit(*str1)) + { + while (*str1 && isdigit(*str1)) + str1++; + + while (*str2 && isdigit(*str2)) + str2++; + + isnum = true; + } + else + { + while (*str1 && isalpha(*str1)) + str1++; + + while (*str2 && isalpha(*str2)) + str2++; + + isnum = false; + } + + oldch1 = *str1; + oldch2 = *str2; + + *str1 = '\0'; + *str2 = '\0'; + + if (one == str1) + return -1; + + if (two == str2) + return (isnum ? 1 : -1); + + if (isnum) + { + int onelen, twolen; + + while (*one == '0') + one++; + + while (*two == '0') + two++; + + onelen = strlen(one); + twolen = strlen(two); + + if (one > two) + return 1; + else if (two > one) + return -1; + } + + ret = strcmp(one, two); + if (ret) + return ret; + + *str1 = oldch1; + *str2 = oldch2; + + one = str1; + two = str2; + } + + if ((!*one) && (!*two)) + return 0; + + if (!*one) + return -1; + + return 1; +} + /* * pkg_verify_graph(root, depth) * diff --git a/pkg.h b/pkg.h index a4a3bea..31e09ae 100644 --- a/pkg.h +++ b/pkg.h @@ -54,6 +54,9 @@ typedef struct tuple_ pkg_tuple_t; #define foreach_list_entry(head, value) \ for ((value) = (head); (value) != NULL; (value) = (value)->next) +#define LOCAL_COPY(a) \ + strcpy(alloca(strlen(a) + 1), a) + struct dependency_ { struct dependency_ *prev, *next; @@ -88,6 +91,7 @@ struct pkg_ { pkg_t *pkg_find(const char *name); void pkg_traverse(pkg_t *root, void (*pkg_traverse_func)(pkg_t *package, void *data), void *data, int maxdepth); void pkg_verify_graph(pkg_t *root, int depth); +int pkg_compare_version(const char *a, const char *b); /* parse.c */ pkg_t *parse_file(const char *path);