Add str_to_version and cmp_version_string into the misc module
authorTomas Mlcoch <tmlcoch@redhat.com>
Thu, 31 May 2012 08:59:37 +0000 (10:59 +0200)
committerTomas Mlcoch <tmlcoch@redhat.com>
Thu, 31 May 2012 08:59:37 +0000 (10:59 +0200)
src/misc.c
src/misc.h
tests/testmisc.c

index 443b555..a0fb46f 100644 (file)
@@ -593,3 +593,116 @@ char *normalize_dir_path(const char *path)
 
     return normalized;
 }
+
+
+struct Version str_to_version(const char *str)
+{
+    char *endptr;
+    const char *ptr = str;
+    struct Version ver;
+    ver.version = 0;
+    ver.release = 0;
+    ver.patch   = 0;
+    ver.suffix  = NULL;
+
+    if (!str || str[0] == '\0') {
+        return ver;
+    }
+
+
+    // Version chunk
+
+    ver.version = strtol(ptr, &endptr, 10);
+    if (!endptr || endptr[0] == '\0') {
+        // Whole string has been converted successfully
+        return ver;
+    } else {
+        if (endptr[0] == '.') {
+            // '.' is supposed to be delimiter -> skip it and go to next chunk
+            ptr = endptr+1;
+        } else {
+            ver.suffix = g_strdup(endptr);
+            return ver;
+        }
+    }
+
+
+    // Release chunk
+
+    ver.release = strtol(ptr, &endptr, 10);
+    if (!endptr || endptr[0] == '\0') {
+        // Whole string has been converted successfully
+        return ver;
+    } else {
+        if (endptr[0] == '.') {
+            // '.' is supposed to be delimiter -> skip it and go to next chunk
+            ptr = endptr+1;
+        } else {
+            ver.suffix = g_strdup(endptr);
+            return ver;
+        }
+    }
+
+
+    // Patch chunk
+
+    ver.patch = strtol(ptr, &endptr, 10);
+    if (!endptr || endptr[0] == '\0') {
+        // Whole string has been converted successfully
+        return ver;
+    } else {
+        if (endptr[0] == '.') {
+            // '.' is supposed to be delimiter -> skip it and go to next chunk
+            ptr = endptr+1;
+        } else {
+            ver.suffix = g_strdup(endptr);
+            return ver;
+        }
+    }
+
+    return ver;
+}
+
+
+// Return values:
+// 0 - versions are same
+// 1 - first string is bigger version
+// 2 - second string is bigger version
+int cmp_version_string(const char* str1, const char *str2)
+{
+    struct Version ver1, ver2;
+
+    if (!str1 && !str2) {
+        return 0;
+    }
+
+    // Get version
+    ver1 = str_to_version(str1);
+    ver2 = str_to_version(str2);
+
+    if (ver1.version > ver2.version) {
+        return 1;
+    } else if (ver1.version < ver2.version) {
+        return 2;
+    } else if (ver1.release > ver2.release) {
+        return 1;
+    } else if (ver1.release < ver2.release) {
+        return 2;
+    } else if (ver1.patch > ver2. patch) {
+        return 1;
+    } else if (ver1.patch < ver2.patch) {
+        return 2;
+    }
+
+    int strcmp_res = g_strcmp0(ver1.suffix, ver2.suffix);
+    if (strcmp_res > 0) {
+        return 1;
+    } else if (strcmp_res < 0) {
+        return 2;
+    }
+
+    g_free(ver1.suffix);
+    g_free(ver2.suffix);
+
+    return 0;
+}
index 4d91bd1..67889a3 100644 (file)
@@ -34,6 +34,16 @@ struct EVR {
     char *release;
 };
 
+
+struct Version {
+    // e.g. for openssl-devel-1.0.0i = version: 1, release: 0, patch: 0, suffix: i
+    long version;
+    long release;
+    long patch;
+    char *suffix;
+};
+
+
 /*
  * BE CAREFULL! Returned structure had all strings malloced!!!
  * Be so kind and don't forget use free() for all its element, before end of structure lifecycle.
@@ -65,4 +75,7 @@ int remove_dir(const char *path);
 // return new allocated string with normalized path or NULL
 char *normalize_dir_path(const char *path);
 
+struct Version str_to_version(const char *str);
+int cmp_version_string(const char* str1, const char *str2);
+
 #endif /* __C_CREATEREPOLIB_MISC_H__ */
index 635f6de..e3d692a 100644 (file)
@@ -760,6 +760,172 @@ static void test_normalize_dir_path(void)
 }
 
 
+static void test_str_to_version(void)
+{
+    struct Version ver;
+
+    ver = str_to_version(NULL);
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("abcd");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "abcd");
+    g_free(ver.suffix);
+
+    ver = str_to_version("0.0.0");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("9");
+    g_assert_cmpint(ver.version, ==, 9);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("3beta");
+    g_assert_cmpint(ver.version, ==, 3);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "beta");
+    g_free(ver.suffix);
+
+    ver = str_to_version("5.2gamma");
+    g_assert_cmpint(ver.version, ==, 5);
+    g_assert_cmpint(ver.release, ==, 2);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "gamma");
+    g_free(ver.suffix);
+
+    ver = str_to_version("0.0.0b");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "b");
+    g_free(ver.suffix);
+
+    ver = str_to_version("2.3.4");
+    g_assert_cmpint(ver.version, ==, 2);
+    g_assert_cmpint(ver.release, ==, 3);
+    g_assert_cmpint(ver.patch, ==, 4);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("11.33.123");
+    g_assert_cmpint(ver.version, ==, 11);
+    g_assert_cmpint(ver.release, ==, 33);
+    g_assert_cmpint(ver.patch, ==, 123);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("1234567.0987654.45678");
+    g_assert_cmpint(ver.version, ==, 1234567);
+    g_assert_cmpint(ver.release, ==, 987654);
+    g_assert_cmpint(ver.patch, ==, 45678);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+
+    ver = str_to_version("1.0.2i");
+    g_assert_cmpint(ver.version, ==, 1);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 2);
+    g_assert_cmpstr(ver.suffix, ==, "i");
+    g_free(ver.suffix);
+
+    ver = str_to_version("1..3");
+    g_assert_cmpint(ver.version, ==, 1);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 3);
+    g_assert_cmpstr(ver.suffix, ==, NULL);
+    g_free(ver.suffix);
+
+    ver = str_to_version("..alpha");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "alpha");
+    g_free(ver.suffix);
+
+    ver = str_to_version("alpha");
+    g_assert_cmpint(ver.version, ==, 0);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "alpha");
+    g_free(ver.suffix);
+
+    ver = str_to_version("1-2-3");
+    g_assert_cmpint(ver.version, ==, 1);
+    g_assert_cmpint(ver.release, ==, 0);
+    g_assert_cmpint(ver.patch, ==, 0);
+    g_assert_cmpstr(ver.suffix, ==, "-2-3");
+    g_free(ver.suffix);
+}
+
+
+static void test_cmp_version_string(void)
+{
+    int ret;
+
+    ret = cmp_version_string(NULL, NULL);
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("", "");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string(NULL, "");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("", NULL);
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("3", "3");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("1", "2");
+    g_assert_cmpint(ret, ==, 2);
+
+    ret = cmp_version_string("99", "8");
+    g_assert_cmpint(ret, ==, 1);
+
+    ret = cmp_version_string("5.4.3", "5.4.3");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("5.3.2", "5.3.1");
+    g_assert_cmpint(ret, ==, 1);
+
+    ret = cmp_version_string("5.3.5", "5.3.6");
+    g_assert_cmpint(ret, ==, 2);
+
+    ret = cmp_version_string("6.3.2a", "6.3.2b");
+    g_assert_cmpint(ret, ==, 2);
+
+    ret = cmp_version_string("6.3.2azb", "6.3.2abc");
+    g_assert_cmpint(ret, ==, 1);
+
+    ret = cmp_version_string("1.2beta", "1.2beta");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("n", "n");
+    g_assert_cmpint(ret, ==, 0);
+
+    ret = cmp_version_string("c", "b");
+    g_assert_cmpint(ret, ==,  1);
+
+    ret = cmp_version_string("c", "f");
+    g_assert_cmpint(ret, ==, 2);
+}
+
+
+
 int main(int argc, char *argv[])
 {
     g_test_init(&argc, &argv, NULL);
@@ -783,6 +949,8 @@ int main(int argc, char *argv[])
     g_test_add("/misc/test_better_copy_file_url", Copyfiletest, NULL, copyfiletest_setup, test_better_copy_file_url, copyfiletest_teardown);
     g_test_add_func("/misc/test_normalize_dir_path", test_normalize_dir_path);
     g_test_add_func("/misc/test_remove_dir", test_remove_dir);
+    g_test_add_func("/misc/test_str_to_version", test_str_to_version);
+    g_test_add_func("/misc/test_cmp_version_string", test_cmp_version_string);
 
     return g_test_run();
 }