NoPaste

mycompare.c

von RobertDebiannutzer

SNIPPET_TEXT:
  1. #include <ctype.h>
  2. #include <limits.h>
  3. #include <locale.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #define ISDIGIT(c)   (isdigit((unsigned char)(c)))
  9.  
  10. static int
  11. get_cur_char(const char *base, const char *str, char *buf)
  12. {
  13.         int r;
  14.  
  15.         /* loop to begin of character */
  16.         while ((r = mblen(str, MB_LEN_MAX)) < 0) {
  17.                 str--;
  18.                 if (str < base) {
  19.                         /* failure (mblen returned -1) */
  20.                         return -1;
  21.                 }
  22.         }
  23.         memcpy(buf, str, r);
  24.         buf[r] = '\0';
  25.  
  26.         return 0;
  27. }
  28.  
  29. static size_t
  30. digit_count(const char *base, const char *str)
  31. {
  32.         size_t d;
  33.  
  34.         for (d=0; ISDIGIT(*str); d++) {
  35.                 str += mblen(str, MB_LEN_MAX);
  36.                 if (str < base) {
  37.                         /* failure (mblen returned -1) */
  38.                         return 0;
  39.                 }
  40.         }
  41.  
  42.         return d;
  43. }
  44.  
  45. /* version compare combined with strcoll */
  46. int
  47. mycompare(const char *s1, const char *s2)
  48. {
  49.         const char *str1 = s1, *str2 = s2;
  50.         char u1[MB_LEN_MAX+1], u2[MB_LEN_MAX+1];
  51.         int rs;
  52.         size_t d1, d2;
  53.  
  54.         for (;; s1++, s2++) {
  55.                 for (; (*s1 == *s2); s1++, s2++) {
  56.                         if (*s1 == '\0') {
  57.                                 /*
  58.                                  * if *s1 == '\0', then *s2 == '\0', too
  59.                                  * (because *s1 == *s2)
  60.                                  *
  61.                                  * if only one of them is '\0', then they
  62.                                  * are not equal any more
  63.                                  */
  64.                                 return 0;
  65.                         }
  66.                 }
  67.                 if ((*s1 == '\0') || (*s2 == '\0')) {
  68.                         return *s1-*s2;
  69.                 }
  70.                 if (get_cur_char(str1, s1, u1) == -1) {
  71.                         return 0;
  72.                 }
  73.                 if (get_cur_char(str2, s2, u2) == -1) {
  74.                         return 0;
  75.                 }
  76.  
  77.                 if ((rs = strcoll(u1, u2)) == 0) {
  78.                         continue;
  79.                 }
  80.  
  81.                 if (ISDIGIT(*s1) && ISDIGIT(*s2)) {
  82.                         /* consider leading zero */
  83.                         if (strcoll(u1, "0") == 0) {
  84.                                 return -1;
  85.                         }
  86.                         if (strcoll(u2, "0") == 0) {
  87.                                 return 1;
  88.                         }
  89.                         /* loop over following digits */
  90.                         if ((d1 = digit_count(str1, s1)) == 0) {
  91.                                 return 0;
  92.                         }
  93.                         if ((d2 = digit_count(str2, s2)) == 0) {
  94.                                 return 0;
  95.                         }
  96.                         /* longer number = greater string */
  97.                         if (d1 != d2) return d1-d2;
  98.                         return rs;
  99.                 } else if (ISDIGIT(*s1)) {
  100.                         return s1-str1 ? 1 : -1;
  101.                 } else if (ISDIGIT(*s2)) {
  102.                         return s2-str2 ? -1 : 1;
  103.                 } else if (rs) {
  104.                         return rs;
  105.                 }
  106.                 /* number = greater string - but only if not at position 0 */
  107.         }
  108. }
  109.  
  110. static int
  111. test_lt(const char *a, const char *b)
  112. {
  113. /*      printf("%d - %d\n",
  114.                         mycompare(a, b),
  115.                         mycompare(b, a));*/
  116.         return (mycompare(a, b) >= 0)
  117.                 +  (mycompare(b, a) <= 0);
  118. }
  119.  
  120. static int
  121. test_eq(const char *a, const char *b)
  122. {
  123.         return mycompare(a, b) != 0;
  124. }
  125.  
  126. int
  127. main(int argc, char *argv[])
  128. {
  129.         unsigned long long i;
  130.  
  131.         setlocale(LC_ALL, "de_DE.UTF-8");
  132.  
  133.         if (argc == 3) {
  134.                 printf("%d\n", mycompare(argv[1], argv[2]));
  135.                 exit(EXIT_SUCCESS);
  136.         } else if (argc == 2 && strcmp(argv[1], "--debug") == 0) {
  137.                 printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n",
  138.                                 test_eq("", ""),
  139.                                 test_lt("0", "1"),
  140.                                 test_lt("1", "2"),
  141.                                 test_lt("a", "b"),
  142.                                 test_lt("abc-1.007.tgz", "abc-1.01a.tgz"),
  143.                                 test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm"),
  144.                                 test_lt("1file", "file1"),
  145.                                 test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  146.                       );
  147.                 exit(EXIT_SUCCESS);
  148.         } else if (argc == 2 && strcmp(argv[1], "--perftest") == 0) {
  149.                 for (i=0; i<1000000; i++) {
  150.                         test_eq("", "");
  151.                         test_lt("0", "1");
  152.                         test_lt("1", "2");
  153.                         test_lt("a", "b");
  154.                         test_lt("abc-1.007.tgz", "abc-1.01a.tgz");
  155.                         test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
  156.                         test_lt("1file", "file1");
  157.                         test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
  158.                 }
  159.         } else if (argc == 1) {
  160.                 return
  161.                         + test_eq("", "")
  162.                         + test_lt("0", "1")
  163.                         + test_lt("1", "2")
  164.                         + test_lt("a", "b")
  165.  
  166.                         + test_lt("abc-1.007.tgz", "abc-1.01a.tgz")
  167.                         + test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  168.                         + test_lt("1file", "file1")
  169.                         + test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  170.                         ;
  171.         } else {
  172.                 fprintf(stderr, "Usage: %s string1 string2\n"
  173.                                 "   or: %s\n"
  174.                                 "   or: %s --debug\n",
  175.                                 argv[0], argv[0], argv[0]);
  176.                 exit(EXIT_FAILURE);
  177.         }
  178. }

Quellcode

Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN