NoPaste

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

Quellcode

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