mycompare.c
von RobertDebiannutzer- SNIPPET_TEXT:
-
- #include <ctype.h>
- #include <limits.h>
- #include <locale.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define ISDIGIT(c) (isdigit((unsigned char)(c)))
- static int
- get_cur_char(const char *base, const char *str, char *buf)
- {
- int r;
- /* loop to begin of character */
- while ((r = mblen(str, MB_LEN_MAX)) < 0) {
- str--;
- if (str < base) {
- /* failure (mblen returned -1) */
- return -1;
- }
- }
- memcpy(buf, str, r);
- buf[r] = '\0';
- return 0;
- }
- static size_t
- digit_count(const char *base, const char *str)
- {
- size_t d;
- for (d=0; ISDIGIT(*str); d++) {
- str += mblen(str, MB_LEN_MAX);
- if (str < base) {
- /* failure (mblen returned -1) */
- return 0;
- }
- }
- return d;
- }
- /* version compare combined with strcoll */
- int
- mycompare(const char *s1, const char *s2)
- {
- const char *str1 = s1, *str2 = s2;
- char u1[MB_LEN_MAX+1], u2[MB_LEN_MAX+1];
- int rs;
- size_t d1, d2;
- for (;; s1++, s2++) {
- for (; (*s1 == *s2); s1++, s2++) {
- if (*s1 == '\0') {
- /*
- * if *s1 == '\0', then *s2 == '\0', too
- * (because *s1 == *s2)
- *
- * if only one of them is '\0', then they
- * are not equal any more
- */
- return 0;
- }
- }
- if ((*s1 == '\0') || (*s2 == '\0')) {
- return *s1-*s2;
- }
- if (get_cur_char(str1, s1, u1) == -1) {
- return 0;
- }
- if (get_cur_char(str2, s2, u2) == -1) {
- return 0;
- }
- if ((rs = strcoll(u1, u2)) == 0) {
- continue;
- }
- if (ISDIGIT(*s1) && ISDIGIT(*s2)) {
- /* consider leading zero */
- if (strcoll(u1, "0") == 0) {
- return -1;
- }
- if (strcoll(u2, "0") == 0) {
- return 1;
- }
- /* loop over following digits */
- if ((d1 = digit_count(str1, s1)) == 0) {
- return 0;
- }
- if ((d2 = digit_count(str2, s2)) == 0) {
- return 0;
- }
- /* longer number = greater string */
- if (d1 != d2) return d1-d2;
- return rs;
- } else if (ISDIGIT(*s1)) {
- return s1-str1 ? 1 : -1;
- } else if (ISDIGIT(*s2)) {
- return s2-str2 ? -1 : 1;
- } else if (rs) {
- return rs;
- }
- /* number = greater string - but only if not at position 0 */
- }
- }
- static int
- test_lt(const char *a, const char *b)
- {
- /* printf("%d - %d\n",
- mycompare(a, b),
- mycompare(b, a));*/
- return (mycompare(a, b) >= 0)
- + (mycompare(b, a) <= 0);
- }
- static int
- test_eq(const char *a, const char *b)
- {
- return mycompare(a, b) != 0;
- }
- int
- main(int argc, char *argv[])
- {
- unsigned long long i;
- setlocale(LC_ALL, "de_DE.UTF-8");
- if (argc == 3) {
- printf("%d\n", mycompare(argv[1], argv[2]));
- exit(EXIT_SUCCESS);
- } else if (argc == 2 && strcmp(argv[1], "--debug") == 0) {
- printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n",
- test_eq("", ""),
- test_lt("0", "1"),
- test_lt("1", "2"),
- test_lt("a", "b"),
- test_lt("abc-1.007.tgz", "abc-1.01a.tgz"),
- test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm"),
- test_lt("1file", "file1"),
- test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- );
- exit(EXIT_SUCCESS);
- } else if (argc == 2 && strcmp(argv[1], "--perftest") == 0) {
- for (i=0; i<1000000; i++) {
- test_eq("", "");
- test_lt("0", "1");
- test_lt("1", "2");
- test_lt("a", "b");
- test_lt("abc-1.007.tgz", "abc-1.01a.tgz");
- test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
- test_lt("1file", "file1");
- test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
- }
- } else if (argc == 1) {
- return
- + test_eq("", "")
- + test_lt("0", "1")
- + test_lt("1", "2")
- + test_lt("a", "b")
- + test_lt("abc-1.007.tgz", "abc-1.01a.tgz")
- + test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- + test_lt("1file", "file1")
- + test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- ;
- } else {
- fprintf(stderr, "Usage: %s string1 string2\n"
- " or: %s\n"
- " or: %s --debug\n",
- argv[0], argv[0], argv[0]);
- exit(EXIT_FAILURE);
- }
- }
Quellcode
Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN