in src/kudu/gutil/strings/numbers.cc [544:662]
bool safe_int_internal(const char* start, const char* end, int base,
IntType* value_p) {
// Consume whitespace.
while (start < end && ascii_isspace(start[0])) {
++start;
}
while (start < end && ascii_isspace(end[-1])) {
--end;
}
if (start >= end) {
return false;
}
// Consume sign.
const bool negative = (start[0] == '-');
if (negative || start[0] == '+') {
++start;
if (start >= end) {
return false;
}
}
// Consume base-dependent prefix.
// base 0: "0x" -> base 16, "0" -> base 8, default -> base 10
// base 16: "0x" -> base 16
// Also validate the base.
if (base == 0) {
if (end - start >= 2 && start[0] == '0' &&
(start[1] == 'x' || start[1] == 'X')) {
base = 16;
start += 2;
} else if (end - start >= 1 && start[0] == '0') {
base = 8;
start += 1;
} else {
base = 10;
}
} else if (base == 16) {
if (end - start >= 2 && start[0] == '0' &&
(start[1] == 'x' || start[1] == 'X')) {
start += 2;
}
} else if (base >= 2 && base <= 36) {
// okay
} else {
return false;
}
// Consume digits.
//
// The classic loop:
//
// for each digit
// value = value * base + digit
// value *= sign
//
// The classic loop needs overflow checking. It also fails on the most
// negative integer, -2147483648 in 32-bit two's complement representation.
//
// My improved loop:
//
// if (!negative)
// for each digit
// value = value * base
// value = value + digit
// else
// for each digit
// value = value * base
// value = value - digit
//
// Overflow checking becomes simple.
//
// I present the positive code first for easier reading.
IntType value = 0;
if (!negative) {
const IntType vmax = std::numeric_limits<IntType>::max();
assert(vmax > 0);
assert(vmax >= base);
const IntType vmax_over_base = vmax / base;
// loop over digits
// loop body is interleaved for perf, not readability
for (; start < end; ++start) {
unsigned char c = static_cast<unsigned char>(start[0]);
int digit = kAsciiToInt[c];
if (value > vmax_over_base) return false;
value *= base;
if (digit >= base) return false;
if (value > vmax - digit) return false;
value += digit;
}
} else {
const IntType vmin = std::numeric_limits<IntType>::min();
assert(vmin < 0);
assert(vmin <= 0 - base);
IntType vmin_over_base = vmin / base;
// 2003 c++ standard [expr.mul]
// "... the sign of the remainder is implementation-defined."
// Although (vmin/base)*base + vmin%base is always vmin.
// 2011 c++ standard tightens the spec but we cannot rely on it.
if (vmin % base > 0) {
vmin_over_base += 1;
}
// loop over digits
// loop body is interleaved for perf, not readability
for (; start < end; ++start) {
unsigned char c = static_cast<unsigned char>(start[0]);
int digit = kAsciiToInt[c];
if (value < vmin_over_base) return false;
value *= base;
if (digit >= base) return false;
if (value < vmin + digit) return false;
value -= digit;
}
}
// Store output.
*value_p = value;
return true;
}