int AutoDigitStrCmp()

in src/kudu/gutil/strings/numbers.cc [1132:1205]


int AutoDigitStrCmp(const char* a, int alen,
                    const char* b, int blen,
                    bool strict) {
  int aindex = 0;
  int bindex = 0;
  while ((aindex < alen) && (bindex < blen)) {
    if (isdigit(a[aindex]) && isdigit(b[bindex])) {
      // Compare runs of digits.  Instead of extracting numbers, we
      // just skip leading zeroes, and then get the run-lengths.  This
      // allows us to handle arbitrary precision numbers.  We remember
      // how many zeroes we found so that we can differentiate between
      // "1" and "01" in strict mode.

      // Skip leading zeroes, but remember how many we found
      int azeroes = aindex;
      int bzeroes = bindex;
      while ((aindex < alen) && (a[aindex] == '0')) aindex++;
      while ((bindex < blen) && (b[bindex] == '0')) bindex++;
      azeroes = aindex - azeroes;
      bzeroes = bindex - bzeroes;

      // Count digit lengths
      int astart = aindex;
      int bstart = bindex;
      while ((aindex < alen) && isdigit(a[aindex])) aindex++;
      while ((bindex < blen) && isdigit(b[bindex])) bindex++;
      if (aindex - astart < bindex - bstart) {
        // a has shorter run of digits: so smaller
        return -1;
      } else if (aindex - astart > bindex - bstart) {
        // a has longer run of digits: so larger
        return 1;
      } else {
        // Same lengths, so compare digit by digit
        for (int i = 0; i < aindex-astart; i++) {
          if (a[astart+i] < b[bstart+i]) {
            return -1;
          } else if (a[astart+i] > b[bstart+i]) {
            return 1;
          }
        }
        // Equal: did one have more leading zeroes?
        if (strict && azeroes != bzeroes) {
          if (azeroes > bzeroes) {
            // a has more leading zeroes: a < b
            return -1;
          } else {
            // b has more leading zeroes: a > b
            return 1;
          }
        }
        // Equal: so continue scanning
      }
    } else if (a[aindex] < b[bindex]) {
      return -1;
    } else if (a[aindex] > b[bindex]) {
      return 1;
    } else {
      aindex++;
      bindex++;
    }
  }

  if (aindex < alen) {
    // b is prefix of a
    return 1;
  } else if (bindex < blen) {
    // a is prefix of b
    return -1;
  } else {
    // a is equal to b
    return 0;
  }
}