Advertisement
Guest User

Untitled

a guest
Sep 25th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.64 KB | None | 0 0
  1. static int rpmvercmp(const char *a, const char *b)
  2. {
  3.     char oldch1, oldch2;
  4.     char *str1, *str2;
  5.     char *ptr1, *ptr2;
  6.     char *one, *two;
  7.     int rc;
  8.     int isnum;
  9.     int ret = 0;
  10.  
  11.     /* easy comparison to see if versions are identical */
  12.     if(strcmp(a, b) == 0) return 0;
  13.  
  14.     str1 = strdup(a);
  15.     str2 = strdup(b);
  16.  
  17.     one = ptr1 = str1;
  18.     two = ptr2 = str2;
  19.  
  20.     /* loop through each version segment of str1 and str2 and compare them */
  21.     while (*one && *two) {
  22.         while (*one && !isalnum((int)*one)) one++;
  23.         while (*two && !isalnum((int)*two)) two++;
  24.  
  25.         /* If we ran to the end of either, we are finished with the loop */
  26.         if (!(*one && *two)) break;
  27.  
  28.         /* If the separator lengths were different, we are also finished */
  29.         if ((one - ptr1) != (two - ptr2)) {
  30.             ret = (one - ptr1) < (two - ptr2) ? -1 : 1;
  31.             goto cleanup;
  32.         }
  33.  
  34.         ptr1 = one;
  35.         ptr2 = two;
  36.  
  37.         /* grab first completely alpha or completely numeric segment */
  38.         /* leave one and two pointing to the start of the alpha or numeric */
  39.         /* segment and walk ptr1 and ptr2 to end of segment */
  40.         if (isdigit((int)*ptr1)) {
  41.             while (*ptr1 && isdigit((int)*ptr1)) ptr1++;
  42.             while (*ptr2 && isdigit((int)*ptr2)) ptr2++;
  43.             isnum = 1;
  44.         } else {
  45.             while (*ptr1 && isalpha((int)*ptr1)) ptr1++;
  46.             while (*ptr2 && isalpha((int)*ptr2)) ptr2++;
  47.             isnum = 0;
  48.         }
  49.  
  50.         /* save character at the end of the alpha or numeric segment */
  51.         /* so that they can be restored after the comparison */
  52.         oldch1 = *ptr1;
  53.         *ptr1 = '\0';
  54.         oldch2 = *ptr2;
  55.         *ptr2 = '\0';
  56.  
  57.         /* this cannot happen, as we previously tested to make sure that */
  58.         /* the first string has a non-null segment */
  59.         if (one == ptr1) {
  60.             ret = -1;   /* arbitrary */
  61.             goto cleanup;
  62.         }
  63.  
  64.         /* take care of the case where the two version segments are */
  65.         /* different types: one numeric, the other alpha (i.e. empty) */
  66.         /* numeric segments are always newer than alpha segments */
  67.         /* XXX See patch #60884 (and details) from bugzilla #50977. */
  68.         if (two == ptr2) {
  69.             ret = isnum ? 1 : -1;
  70.             goto cleanup;
  71.         }
  72.  
  73.         if (isnum) {
  74.             /* this used to be done by converting the digit segments */
  75.             /* to ints using atoi() - it's changed because long  */
  76.             /* digit segments can overflow an int - this should fix that. */
  77.  
  78.             /* throw away any leading zeros - it's a number, right? */
  79.             while (*one == '0') one++;
  80.             while (*two == '0') two++;
  81.  
  82.             /* whichever number has more digits wins */
  83.             if (strlen(one) > strlen(two)) {
  84.                 ret = 1;
  85.                 goto cleanup;
  86.             }
  87.             if (strlen(two) > strlen(one)) {
  88.                 ret = -1;
  89.                 goto cleanup;
  90.             }
  91.         }
  92.  
  93.         /* strcmp will return which one is greater - even if the two */
  94.         /* segments are alpha or if they are numeric.  don't return  */
  95.         /* if they are equal because there might be more segments to */
  96.         /* compare */
  97.         rc = strcmp(one, two);
  98.         if (rc) {
  99.             ret = rc < 1 ? -1 : 1;
  100.             goto cleanup;
  101.         }
  102.  
  103.         /* restore character that was replaced by null above */
  104.         *ptr1 = oldch1;
  105.         one = ptr1;
  106.         *ptr2 = oldch2;
  107.         two = ptr2;
  108.     }
  109.  
  110.     /* this catches the case where all numeric and alpha segments have */
  111.     /* compared identically but the segment separating characters were */
  112.     /* different */
  113.     if ((!*one) && (!*two)) {
  114.         ret = 0;
  115.         goto cleanup;
  116.     }
  117.  
  118.     /* the final showdown. we never want a remaining alpha string to
  119.      * beat an empty string. the logic is a bit weird, but:
  120.      * - if one is empty and two is not an alpha, two is newer.
  121.      * - if one is an alpha, two is newer.
  122.      * - otherwise one is newer.
  123.      * */
  124.     if ( (!*one && !isalpha((int)*two))
  125.             || isalpha((int)*one) ) {
  126.         ret = -1;
  127.     } else {
  128.         ret = 1;
  129.     }
  130.  
  131. cleanup:
  132.     free(str1);
  133.     free(str2);
  134.     return ret;
  135. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement