int DataSource::from_kvpair()

in util/installer.cc [790:890]


int DataSource::from_kvpair(const SQLWCHAR *str, SQLWCHAR delim)
{
  const SQLWCHAR *split;
  const SQLWCHAR *end;
  SQLWCHAR attribute[1000];
  size_t len;

  while (*str)
  {
    if ((split= sqlwcharchr(str, (SQLWCHAR)'=')) == NULL)
      return 1;

    /* remove leading spaces on attribute */
    while (*str == ' ')
      ++str;
    len = split - str;

    // The attribute length must not be out of buf
    if (len >= sizeof(attribute)/sizeof(SQLWCHAR))
    {
      return 1;
    }

    memcpy(attribute, str, len * sizeof(SQLWCHAR));
    attribute[len]= 0;
    /* remove trailing spaces on attribute */
    --len;
    while (attribute[len] == ' ')
    {
      attribute[len] = 0;
      --len;
    }

    /* remove leading and trailing spaces on value */
    while (*(++split) == ' ');

    auto find_bracket_end = [](const SQLWCHAR *wstr) {
      const SQLWCHAR *e = wstr;
      do
      {
        e = sqlwcharchr(e, '}');
        if (e == nullptr || *(e + 1) == 0)
          break;

        // Found escape }}, skip to the next bracket
        if (*(e + 1) == '}')
          e += 2;
        else
          break;

      } while (*e);
      return e;
    };

    /* check for an "escaped" value */
    if ((*split == '{' && (end = find_bracket_end(str)) == NULL) ||
        /* or a delimited value */
        (*split != '{' && (end= sqlwcharchr(str, delim)) == NULL))
      /* otherwise, take the rest of the string */
      end= str + sqlwcharlen(str);

    /* remove trailing spaces on value (not escaped part) */
    len = end - split - 1;
    while (end > split && split[len] == ' ' && split[len+1] != '}')
    {
      --len;
      --end;
    }

    /* handle deprecated options as an exception */
    if (!sqlwcharcasecmp(W_OPTION, attribute))
    {
      set_numeric_options(sqlwchartoul(split));
    }
    else
    {
      if (optionBase *opt = get_opt(attribute)) {

        if (opt->get_type() == optionBase::opt_type::STRING) {
          optionStr *str_opt = dynamic_cast<optionStr*>(opt);
          if (*split == '{' && *end == '}') {
            str_opt->set_remove_brackets(split + 1, (SQLINTEGER)(end - split - 1));
            ++end;
          } else {
            str_opt->set_remove_brackets(split, (SQLINTEGER)(end - split));
          }
        } else {
          *opt = split;
        }
      }
    }

    str= end;
    /* If delim is NULL then double-NULL is the end of key-value pairs list */
    while ((delim && *str == delim) ||
           (!delim && !*str && *(str+1)) ||
           *str == ' ')
      ++str;
  }
  return 0;
}