static int32_t _az_json_writer_escaped_length()

in sdk/src/azure/core/az_json_writer.c [207:283]


static int32_t _az_json_writer_escaped_length(
    az_span value,
    int32_t* out_index_of_first_escaped_char,
    bool break_on_first_escaped)
{
  _az_PRECONDITION_NOT_NULL(out_index_of_first_escaped_char);
  _az_PRECONDITION_VALID_SPAN(value, 0, true);

  int32_t value_size = az_span_size(value);
  _az_PRECONDITION(value_size <= _az_MAX_UNESCAPED_STRING_SIZE);

  int32_t escaped_length = 0;
  *out_index_of_first_escaped_char = -1;

  int32_t i = 0;
  uint8_t* value_ptr = az_span_ptr(value);

  while (i < value_size)
  {
    uint8_t const ch = value_ptr[i];

    switch (ch)
    {
      case '\\':
      case '"':
      case '\b':
      case '\f':
      case '\n':
      case '\r':
      case '\t':
      {
        escaped_length += 2; // Use the two-character sequence escape for these.
        break;
      }
      default:
      {
        // Check if the character has to be escaped as a UNICODE escape sequence.
        if (ch < _az_ASCII_SPACE_CHARACTER)
        {
          escaped_length += _az_MAX_EXPANSION_FACTOR_WHILE_ESCAPING;
        }
        else
        {
          escaped_length++; // No escaping required.
        }
        break;
      }
    }

    i++;

    // If this is the first time that we found a character that needs to be escaped,
    // set out_index_of_first_escaped_char to the corresponding index.
    // If escaped_length == i, then we haven't found a character that needs to be escaped yet.
    if (escaped_length != i && *out_index_of_first_escaped_char == -1)
    {
      *out_index_of_first_escaped_char = i - 1;
      if (break_on_first_escaped)
      {
        break;
      }
    }

    // If the length overflows, in case the precondition is not honored, stop processing and break
    // The caller will return AZ_ERROR_NOT_ENOUGH_SPACE since az_span can't contain it.
    // TODO: Consider removing this if it is too costly.
    if (escaped_length < 0)
    {
      escaped_length = INT32_MAX;
      break;
    }
  }

  // In most common cases, escaped_length will equal value_size and out_index_of_first_escaped_char
  // will be -1.
  return escaped_length;
}