AZ_NODISCARD static az_result _az_json_reader_process_string()

in sdk/src/azure/core/az_json_reader.c [240:355]


AZ_NODISCARD static az_result _az_json_reader_process_string(az_json_reader* ref_json_reader)
{
  // Move past the first '"' character
  ref_json_reader->_internal.bytes_consumed++;

  az_span token = _get_remaining_json(ref_json_reader);
  int32_t remaining_size = az_span_size(token);

  if (remaining_size < 1)
  {
    _az_RETURN_IF_FAILED(_az_json_reader_get_next_buffer(ref_json_reader, &token, false));
    remaining_size = az_span_size(token);
  }

  int32_t current_index = 0;
  int32_t string_length = 0;
  uint8_t* token_ptr = az_span_ptr(token);
  uint8_t next_byte = token_ptr[0];

  // Clear the state of any previous string token.
  ref_json_reader->token._internal.string_has_escaped_chars = false;

  while (true)
  {
    if (next_byte == '"')
    {
      break;
    }

    if (next_byte == '\\')
    {
      ref_json_reader->token._internal.string_has_escaped_chars = true;
      current_index++;
      string_length++;
      if (current_index >= remaining_size)
      {
        _az_RETURN_IF_FAILED(_az_json_reader_get_next_buffer(ref_json_reader, &token, false));
        current_index = 0;
        token_ptr = az_span_ptr(token);
        remaining_size = az_span_size(token);
      }
      next_byte = token_ptr[current_index];

      if (next_byte == 'u')
      {
        current_index++;
        string_length++;

        // Expecting 4 hex digits to follow the escaped 'u'
        for (int32_t i = 0; i < 4; i++)
        {
          if (current_index >= remaining_size)
          {
            _az_RETURN_IF_FAILED(_az_json_reader_get_next_buffer(ref_json_reader, &token, false));
            current_index = 0;
            token_ptr = az_span_ptr(token);
            remaining_size = az_span_size(token);
          }

          string_length++;
          next_byte = token_ptr[current_index++];

          if (!isxdigit(next_byte))
          {
            return AZ_ERROR_UNEXPECTED_CHAR;
          }
        }

        // We have already skipped past the u and 4 hex digits. The loop accounts for incrementing
        // by 1 more, so subtract one to account for that.
        current_index--;
        string_length--;
      }
      else
      {
        if (!_az_is_valid_escaped_character(next_byte))
        {
          return AZ_ERROR_UNEXPECTED_CHAR;
        }
      }
    }
    else
    {
      // Control characters are invalid within a JSON string and should be correctly escaped.
      if (next_byte < _az_ASCII_SPACE_CHARACTER)
      {
        return AZ_ERROR_UNEXPECTED_CHAR;
      }
    }

    current_index++;
    string_length++;

    if (current_index >= remaining_size)
    {
      _az_RETURN_IF_FAILED(_az_json_reader_get_next_buffer(ref_json_reader, &token, false));
      current_index = 0;
      token_ptr = az_span_ptr(token);
      remaining_size = az_span_size(token);
    }
    next_byte = token_ptr[current_index];
  }

  _az_json_reader_update_state(
      ref_json_reader,
      AZ_JSON_TOKEN_STRING,
      az_span_slice(token, 0, current_index),
      current_index,
      string_length);

  // Add 1 to number of bytes consumed to account for the last '"' character.
  ref_json_reader->_internal.bytes_consumed++;
  ref_json_reader->_internal.total_bytes_consumed++;

  return AZ_OK;
}