in sdk/src/azure/core/az_span.c [103:154]
AZ_NODISCARD az_result az_span_atou64(az_span source, uint64_t* out_number)
{
_az_PRECONDITION_VALID_SPAN(source, 1, false);
_az_PRECONDITION_NOT_NULL(out_number);
int32_t const span_size = az_span_size(source);
if (span_size < 1)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
// If the first character is not a digit or an optional + sign, return error.
int32_t starting_index = 0;
uint8_t* source_ptr = az_span_ptr(source);
uint8_t next_byte = source_ptr[0];
if (!isdigit(next_byte))
{
// There must be another byte after a sign.
// The loop below checks that it must be a digit.
if (next_byte != '+' || span_size < 2)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
starting_index++;
}
uint64_t value = 0;
for (int32_t i = starting_index; i < span_size; ++i)
{
next_byte = source_ptr[i];
if (!isdigit(next_byte))
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
uint64_t const d = (uint64_t)next_byte - '0';
// Check whether the next digit will cause an integer overflow.
// Before actually doing the math below, this is checking whether value * 10 + d > UINT64_MAX.
if ((UINT64_MAX - d) / _az_NUMBER_OF_DECIMAL_VALUES < value)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
value = value * _az_NUMBER_OF_DECIMAL_VALUES + d;
}
*out_number = value;
return AZ_OK;
}