static std::size_t span_quotable_string_literal()

in mysqlshdk/libs/utils/utils_general.cc [507:647]


static std::size_t span_quotable_string_literal(
    const std::string &s, std::size_t p, std::string *out_string,
    bool allow_number_at_beginning = false) {
  if (s.size() <= p) return p;

  char quote = s[p];
  if (quote != '\'' && quote != '"') {
    // check if valid initial char
    if (!std::isalpha(quote) &&
        !(allow_number_at_beginning && std::isdigit(quote)) && quote != '_' &&
        quote != '$' && quote != '%')
      throw std::runtime_error("Invalid character in string literal");
    quote = 0;
  } else {
    p++;
  }

  if (quote == 0) {
    while (p < s.size()) {
      if (!std::isalnum(s[p]) && s[p] != '_' && s[p] != '$' && s[p] != '.' &&
          s[p] != '%')
        break;
      if (out_string) out_string->push_back(s[p]);
      ++p;
    }
  } else {
    int esc = 0;
    bool done = false;
    while (p < s.size() && !done) {
      if (esc == quote && s[p] != esc) {
        done = true;
        break;
      }
      switch (s[p]) {
        case '"':
        case '\'':
          if (quote == s[p]) {
            if (esc == quote || esc == '\\') {
              if (out_string) out_string->push_back(s[p]);
              esc = 0;
            } else {
              esc = s[p];
            }
          } else {
            if (out_string) out_string->push_back(s[p]);
            esc = 0;
          }
          break;
        case '\\':
          if (esc == '\\') {
            if (out_string) out_string->push_back(s[p]);
            esc = 0;
          } else if (esc == 0) {
            esc = '\\';
          } else {
            done = true;
          }
          break;
        case 'n':
          if (esc == '\\') {
            if (out_string) out_string->push_back('\n');
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        case 't':
          if (esc == '\\') {
            if (out_string) out_string->push_back('\t');
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        case 'b':
          if (esc == '\\') {
            if (out_string) out_string->push_back('\b');
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        case 'r':
          if (esc == '\\') {
            if (out_string) out_string->push_back('\r');
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        case '0':
          if (esc == '\\') {
            if (out_string) out_string->push_back('\0');
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        case 'Z':
          if (esc == '\\') {
            if (out_string) {
              out_string->push_back(26);
            }
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
        default:
          if (esc == '\\') {
            if (out_string) out_string->push_back(s[p]);
            esc = 0;
          } else if (esc == 0) {
            if (out_string) out_string->push_back(s[p]);
          } else {
            done = true;
          }
          break;
      }
      ++p;
    }
    if (!done && esc == quote) {
      done = true;
    } else if (!done) {
      throw std::runtime_error("Invalid syntax in string literal");
    }
  }
  return p;
}