in sdk/src/azure/core/az_json_token.c [380:481]
AZ_NODISCARD az_result az_json_token_get_string(
az_json_token const* json_token,
char* destination,
int32_t destination_max_size,
int32_t* out_string_length)
{
_az_PRECONDITION_NOT_NULL(json_token);
_az_PRECONDITION_NOT_NULL(destination);
_az_PRECONDITION(destination_max_size > 0);
if (json_token->kind != AZ_JSON_TOKEN_STRING && json_token->kind != AZ_JSON_TOKEN_PROPERTY_NAME)
{
return AZ_ERROR_JSON_INVALID_STATE;
}
az_span token_slice = json_token->slice;
int32_t token_size = json_token->size;
// There is nothing to unescape here, copy directly.
if (!json_token->_internal.string_has_escaped_chars)
{
// We need enough space to add a null terminator.
if (token_size >= destination_max_size)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
// Contiguous token
if (!json_token->_internal.is_multisegment)
{
// This will add a null terminator.
az_span_to_str(destination, destination_max_size, token_slice);
}
else
{
// Token straddles more than one segment
az_span remainder = _az_json_token_copy_into_span_helper(
json_token, az_span_create((uint8_t*)destination, destination_max_size));
// Add a null terminator.
az_span_copy_u8(remainder, 0);
}
if (out_string_length != NULL)
{
*out_string_length = token_size;
}
return AZ_OK;
}
// No need to try to unescape the token slice, if the destination is known to be too small.
// Unescaping always shrinks the string, at most by a factor of 6.
// We also need enough space to add a null terminator.
if (token_size / _az_MAX_EXPANSION_FACTOR_WHILE_ESCAPING >= destination_max_size)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
int32_t dest_idx = 0;
bool next_char_escaped = false;
// Contiguous token
if (!json_token->_internal.is_multisegment)
{
_az_RETURN_IF_FAILED(_az_json_token_get_string_helper(
token_slice, destination, destination_max_size, &dest_idx, &next_char_escaped));
}
else
{
// Token straddles more than one segment
for (int32_t i = json_token->_internal.start_buffer_index;
i <= json_token->_internal.end_buffer_index;
i++)
{
az_span source = json_token->_internal.pointer_to_first_buffer[i];
if (i == json_token->_internal.start_buffer_index)
{
source = az_span_slice_to_end(source, json_token->_internal.start_buffer_offset);
}
else if (i == json_token->_internal.end_buffer_index)
{
source = az_span_slice(source, 0, json_token->_internal.end_buffer_offset);
}
_az_RETURN_IF_FAILED(_az_json_token_get_string_helper(
source, destination, destination_max_size, &dest_idx, &next_char_escaped));
}
}
if (dest_idx >= destination_max_size)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
destination[dest_idx] = 0;
if (out_string_length != NULL)
{
*out_string_length = dest_idx;
}
return AZ_OK;
}