SQLite Forum

UINT extension tweak suggestion
Login

UINT extension tweak suggestion

(1) By Mark Scandariato (scandariato) on 2021-11-30 16:20:12 [source]

I guess I missed all the fun last year, having just noticed this extension.

I see that it may scan its inputs twice. This similar function only scans its inputs once, using the fact that big-endian numbers of the same length can be sorted by their leftmost different digit. (I've been using it for a "version" collating sequence, to order semantic versions.)

#define are_digits(a, b) (isdigit(a) && isdigit(b))

static int versioncmp (void *state, int len1, const void *v1, int len2, const void *v2)
{
    (void)state;
    const unsigned char *a = v1;
    const unsigned char *b = v2;
    int i = 0;
    int j = 0;
    int rc = 0;
    while (rc==0 && i<len1 && j<len2) {
        if (!are_digits(a[i], b[j])) {
            rc = a[i] - b[j];
        } else {
            // skip leading zeros
            while (i<len1 && a[i] == '0') i++;
            while (j<len2 && b[j] == '0') j++;
            // compare pairs of digits until we run out of pairs
            for (; i<len1 && j<len2 && are_digits(a[i], b[j]); i++, j++) {
                // latch the leftmost difference
                if (!rc) rc = a[i] - b[j];
            }
            // does one string have more digits?
            if (i<len1 && isdigit(a[i])) return +1;
            if (j<len2 && isdigit(b[j])) return -1;
            continue;
        }
        i++;
        j++;
    }
    return rc ? rc : (len1 - i) - (len2 - j);
}