Skip to content

Commit

Permalink
bring in unescape in place
Browse files Browse the repository at this point in the history
  • Loading branch information
ahsonkhan authored and danewalton committed Sep 15, 2022
1 parent 3233d8a commit d84c438
Show file tree
Hide file tree
Showing 3 changed files with 455 additions and 0 deletions.
27 changes: 27 additions & 0 deletions sdk/inc/azure/core/az_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,33 @@ AZ_NODISCARD az_result az_json_reader_next_token(az_json_reader* ref_json_reader
*/
AZ_NODISCARD az_result az_json_reader_skip_children(az_json_reader* ref_json_reader);

/**
* @brief Unescapes the JSON string within the provided #az_span.
*
* @param[in] json_string The #az_span that contains the string to be unescaped.
* @param destination Pointer to the buffer that will contain the output.
* @param[in] destination_max_size The maximum available space within the buffer referred to by
* \p destination.
* @param[out] out_string_length __[nullable]__ Contains the number of bytes written to the
* \p destination which denote the length of the unescaped string. If `NULL` is passed, the
* \p parameter is ignored.
*
* @return An #az_result value indicating the result of the operation.
* @retval #AZ_OK The string is returned.
* @retval #AZ_ERROR_NOT_ENOUGH_SPACE \p destination does not have enough size.
*
* @remarks The buffer referred to by \p destination must have a size that is at least 1 byte bigger
* than the \p json_string #az_span for the \p destination string to be zero-terminated.
* Content is copied from the source buffer, while unescaping and then `\0` is added at the end.
*
* @remarks This API can also be used to perform in place unescaping.
*/
AZ_NODISCARD az_result az_json_string_unescape(
az_span json_string,
char* destination,
int32_t destination_max_size,
int32_t* out_string_length);

#include <azure/core/_az_cfg_suffix.h>

#endif // _az_JSON_H
56 changes: 56 additions & 0 deletions sdk/src/azure/core/az_json_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,62 @@ AZ_NODISCARD static az_result _az_json_token_get_string_helper(
return AZ_OK;
}

AZ_NODISCARD az_result az_json_string_unescape(
az_span json_string,
char* destination,
int32_t destination_max_size,
int32_t* out_string_length)
{
_az_PRECONDITION_VALID_SPAN(json_string, 1, false);
_az_PRECONDITION_NOT_NULL(destination);
// The destination needs to be larger than the input, for null terminator.
_az_PRECONDITION(destination_max_size > az_span_size(json_string));

int32_t position = 0;
int32_t span_size = az_span_size(json_string);
uint8_t* span_ptr = az_span_ptr(json_string);
for (int32_t i = 0; i < span_size; i++)
{
uint8_t current_char = span_ptr[i];
if (current_char == '\\' && i < span_size - 1)
{
uint8_t next_char = span_ptr[i + 1];
// check that we have something to escape
if (_az_is_valid_escaped_character(next_char))
{
current_char = _az_json_unescape_single_byte(next_char);
i++;
}
else
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
}
else if (current_char == '\\')
{
// At this point, we are at the last character, i == span_size - 1
return AZ_ERROR_UNEXPECTED_END;
}

if (position > destination_max_size)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}

destination[position] = (char)current_char;
position++;
}

destination[position] = 0;

if (out_string_length != NULL)
{
*out_string_length = position;
}

return AZ_OK;
}

AZ_NODISCARD az_result az_json_token_get_string(
az_json_token const* json_token,
char* destination,
Expand Down
Loading

0 comments on commit d84c438

Please sign in to comment.