in absl/strings/numbers.cc [633:700]
inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
int* base_ptr /*inout*/,
bool* negative_ptr /*output*/) {
if (text->data() == nullptr) {
return false;
}
const char* start = text->data();
const char* end = start + text->size();
int base = *base_ptr;
// Consume whitespace.
while (start < end && absl::ascii_isspace(start[0])) {
++start;
}
while (start < end && absl::ascii_isspace(end[-1])) {
--end;
}
if (start >= end) {
return false;
}
// Consume sign.
*negative_ptr = (start[0] == '-');
if (*negative_ptr || 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;
if (start >= end) {
// "0x" with no digits after is invalid.
return false;
}
} 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;
if (start >= end) {
// "0x" with no digits after is invalid.
return false;
}
}
} else if (base >= 2 && base <= 36) {
// okay
} else {
return false;
}
*text = absl::string_view(start, end - start);
*base_ptr = base;
return true;
}