in sdk/src/azure/core/az_json_reader.c [497:697]
AZ_NODISCARD static az_result _az_json_reader_process_number(az_json_reader* ref_json_reader)
{
az_span token = _get_remaining_json(ref_json_reader);
int32_t total_consumed = 0;
int32_t current_consumed = 0;
uint8_t next_byte = az_span_ptr(token)[0];
if (next_byte == '-')
{
total_consumed++;
current_consumed++;
// A negative sign must be followed by at least one digit.
_az_RETURN_IF_FAILED(
_az_validate_next_byte_is_digit(ref_json_reader, &token, ¤t_consumed));
next_byte = az_span_ptr(token)[current_consumed];
}
if (next_byte == '0')
{
total_consumed++;
current_consumed++;
if (current_consumed >= az_span_size(token))
{
if (az_result_failed(_az_json_reader_get_next_buffer(ref_json_reader, &token, false)))
{
// If there is no more JSON, this is a valid end state only when the JSON payload contains a
// single value: "[-]0"
// Otherwise, the payload is incomplete and ending too early.
return _az_json_reader_update_number_state_if_single_value(
ref_json_reader,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
current_consumed = 0;
}
next_byte = az_span_ptr(token)[current_consumed];
az_result result = AZ_OK;
if (_az_finished_consuming_json_number(next_byte, AZ_SPAN_FROM_STR(".eE"), &result))
{
if (az_result_succeeded(result))
{
_az_json_reader_update_state(
ref_json_reader,
AZ_JSON_TOKEN_NUMBER,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
return result;
}
}
else
{
_az_PRECONDITION(isdigit(next_byte));
// Integer part before decimal
_az_json_reader_consume_digits(ref_json_reader, &token, ¤t_consumed, &total_consumed);
if (current_consumed >= az_span_size(token))
{
if (az_result_failed(_az_json_reader_get_next_buffer(ref_json_reader, &token, false)))
{
// If there is no more JSON, this is a valid end state only when the JSON payload contains a
// single value: "[-][digits]"
// Otherwise, the payload is incomplete and ending too early.
return _az_json_reader_update_number_state_if_single_value(
ref_json_reader,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
current_consumed = 0;
}
next_byte = az_span_ptr(token)[current_consumed];
az_result result = AZ_OK;
if (_az_finished_consuming_json_number(next_byte, AZ_SPAN_FROM_STR(".eE"), &result))
{
if (az_result_succeeded(result))
{
_az_json_reader_update_state(
ref_json_reader,
AZ_JSON_TOKEN_NUMBER,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
return result;
}
}
if (next_byte == '.')
{
total_consumed++;
current_consumed++;
// A decimal point must be followed by at least one digit.
_az_RETURN_IF_FAILED(
_az_validate_next_byte_is_digit(ref_json_reader, &token, ¤t_consumed));
// Integer part after decimal
_az_json_reader_consume_digits(ref_json_reader, &token, ¤t_consumed, &total_consumed);
if (current_consumed >= az_span_size(token))
{
if (az_result_failed(_az_json_reader_get_next_buffer(ref_json_reader, &token, false)))
{
// If there is no more JSON, this is a valid end state only when the JSON payload contains a
// single value: "[-][digits].[digits]"
// Otherwise, the payload is incomplete and ending too early.
return _az_json_reader_update_number_state_if_single_value(
ref_json_reader,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
current_consumed = 0;
}
next_byte = az_span_ptr(token)[current_consumed];
az_result result = AZ_OK;
if (_az_finished_consuming_json_number(next_byte, AZ_SPAN_FROM_STR("eE"), &result))
{
if (az_result_succeeded(result))
{
_az_json_reader_update_state(
ref_json_reader,
AZ_JSON_TOKEN_NUMBER,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
return result;
}
}
// Move past 'e'/'E'
total_consumed++;
current_consumed++;
// The 'e'/'E' character must be followed by a sign or at least one digit.
if (current_consumed >= az_span_size(token))
{
_az_RETURN_IF_FAILED(_az_json_reader_get_next_buffer(ref_json_reader, &token, false));
current_consumed = 0;
}
next_byte = az_span_ptr(token)[current_consumed];
if (next_byte == '-' || next_byte == '+')
{
total_consumed++;
current_consumed++;
// A sign must be followed by at least one digit.
_az_RETURN_IF_FAILED(
_az_validate_next_byte_is_digit(ref_json_reader, &token, ¤t_consumed));
}
// Integer part after the 'e'/'E'
_az_json_reader_consume_digits(ref_json_reader, &token, ¤t_consumed, &total_consumed);
if (current_consumed >= az_span_size(token))
{
if (az_result_failed(_az_json_reader_get_next_buffer(ref_json_reader, &token, false)))
{
// If there is no more JSON, this is a valid end state only when the JSON payload contains a
// single value: "[-][digits].[digits]e[+|-][digits]"
// Otherwise, the payload is incomplete and ending too early.
return _az_json_reader_update_number_state_if_single_value(
ref_json_reader,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
}
current_consumed = 0;
}
// Checking if we are done processing a JSON number
next_byte = az_span_ptr(token)[current_consumed];
int32_t index = az_span_find(json_delimiters, az_span_create(&next_byte, 1));
if (index == -1)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
_az_json_reader_update_state(
ref_json_reader,
AZ_JSON_TOKEN_NUMBER,
az_span_slice(token, 0, current_consumed),
current_consumed,
total_consumed);
return AZ_OK;
}