AZ_NODISCARD az_result az_span_atod()

in sdk/src/azure/core/az_span.c [366:399]


AZ_NODISCARD az_result az_span_atod(az_span source, double* out_number)
{
  _az_PRECONDITION_VALID_SPAN(source, 1, false);
  _az_PRECONDITION_NOT_NULL(out_number);

  int32_t size = az_span_size(source);

  _az_PRECONDITION_RANGE(1, size, _az_MAX_SIZE_FOR_PARSING_DOUBLE);

  // This check is necessary to prevent sscanf from reading bytes past the end of the span, when the
  // span might contain whitespace or other invalid bytes at the start.
  uint8_t* source_ptr = az_span_ptr(source);
  if (size < 1 || !_is_valid_start_of_double(source_ptr[0]))
  {
    return AZ_ERROR_UNEXPECTED_CHAR;
  }

  // Stack based string to allow thread-safe mutation.
  // The length is 8 to allow space for the null-terminating character.
  // NOLINTNEXTLINE(readability-magic-numbers,  cppcoreguidelines-avoid-magic-numbers)
  char format[8] = "%00lf%n";

  // Starting at 1 to skip the '%' character
  format[1] = (char)((size / _az_NUMBER_OF_DECIMAL_VALUES) + '0');
  format[2] = (char)((size % _az_NUMBER_OF_DECIMAL_VALUES) + '0');

  int32_t chars_consumed = 0;
  // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
  int32_t n = sscanf((char*)source_ptr, format, out_number, &chars_consumed);

  // Success if the entire source was consumed by sscanf and it set the out_number argument.
  return (size == chars_consumed && n == 1 && _az_isfinite(*out_number)) ? AZ_OK
                                                                         : AZ_ERROR_UNEXPECTED_CHAR;
}