Value expr_getDelimitedField()

in extensions/expression-language/Expression.cpp [270:388]


Value expr_getDelimitedField(const std::vector<Value> &args) {
  const auto &subject = args[0].asString();
  const auto &index = args[1].asUnsignedLong() - 1;
  char delimiter_ch = ',';

  if (args.size() > 2) {
    delimiter_ch = args[2].asString()[0];
  }

  char quote_ch = '"';

  if (args.size() > 3) {
    quote_ch = args[3].asString()[0];
  }

  char escape_ch = '\\';

  if (args.size() > 4) {
    escape_ch = args[4].asString()[0];
  }

  bool strip_chars = false;

  if (args.size() > 5) {
    strip_chars = args[5].asBoolean();
  }

  enum parse_states {
    value,
    quote
  };

  parse_states parse_state = value;
  uint64_t field_idx = 0;
  size_t field_size = 0;
  std::string result;
  result.resize(1024);

  for (size_t parse_pos = 0; parse_pos < subject.length(); parse_pos++) {
    char cur_ch = subject[parse_pos];

    if (cur_ch == escape_ch) {
      if (!strip_chars && field_idx == index) {
        field_size++;

        if (field_size >= result.size()) {
          result.resize(result.size() + 1024);
        }

        result[field_size - 1] = escape_ch;
      }
      parse_pos++;
      if (parse_pos < subject.length()) {
        cur_ch = subject[parse_pos];
      } else {
        break;
      }
    }

    switch (parse_state) {
      case value:
        if (cur_ch == delimiter_ch) {
          field_idx++;
          if (field_idx > index) {
            break;
          }
          continue;
        } else if (cur_ch == quote_ch) {
          if (!strip_chars && field_idx == index) {
            field_size++;

            if (field_size >= result.size()) {
              result.resize(result.size() + 1024);
            }

            result[field_size - 1] = quote_ch;
          }
          parse_state = quote;
          continue;
        } else if (field_idx == index) {
          field_size++;

          if (field_size >= result.size()) {
            result.resize(result.size() + 1024);
          }

          result[field_size - 1] = cur_ch;
        }
        break;
      case quote:
        if (cur_ch == quote_ch) {
          if (!strip_chars && field_idx == index) {
            field_size++;

            if (field_size >= result.size()) {
              result.resize(result.size() + 1024);
            }

            result[field_size - 1] = quote_ch;
          }
          parse_state = value;
          continue;
        } else if (field_idx == index) {
          field_size++;

          if (field_size >= result.size()) {
            result.resize(result.size() + 1024);
          }

          result[field_size - 1] = cur_ch;
        }
        break;
    }
  }

  result.resize(field_size);

  return Value(result);
}