Status RPIServiceImpl::loaderGetVariables()

in src/RLoader.cpp [197:276]


Status RPIServiceImpl::loaderGetVariables(ServerContext* context, const GetVariablesRequest* request, VariablesResponse* response) {
  executeOnMainThread([&] {
    ShieldSEXP obj = dereference(request->obj());
    R_xlen_t reqStart = request->start();
    R_xlen_t reqEnd = request->end();
    if (reqEnd == -1) reqEnd = std::numeric_limits<R_xlen_t>::max();
    if (obj.type() == ENVSXP) {
      response->set_isenv(true);
      if (request->onlyfunctions() && request->nofunctions()) return;
      ShieldSEXP ls = RI->ls(named("envir", obj), named("all.names", !request->nohidden()));
      if (ls.type() != STRSXP) return;
      R_xlen_t length = ls.length();
      if (request->onlyfunctions() || request->nofunctions()) {
        R_xlen_t j = 0;
        for (R_xlen_t i = 0; i < length; ++i) {
          ShieldSEXP x = obj.getVar(stringEltNative(ls, i), false);
          bool isFunc = x.type() == CLOSXP || x.type() == BUILTINSXP || x.type() == SPECIALSXP;
          if (isFunc == request->onlyfunctions()) {
            if (reqStart <= j && j < reqEnd) {
              VariablesResponse::Variable *var = response->add_vars();
              std::string name = stringEltUTF8(ls, i);
              trim(name);
              var->set_name(name);
              getValueInfo(x, var->mutable_value());
            }
            ++j;
          }
        }
        response->set_totalcount(j);
      } else {
        response->set_totalcount(ls.length());
        for (int i = std::max<R_xlen_t>(0, reqStart); i < std::min(length, reqEnd); ++i) {
          VariablesResponse::Variable *var = response->add_vars();
          std::string name = stringEltUTF8(ls, i);
          trim(name);
          var->set_name(name);
          getValueInfo(obj.getVar(stringEltNative(ls, i), false), var->mutable_value());
        }
      }
      return;
    }
    response->set_isenv(false);
    if (obj.type() == LISTSXP || obj.type() == DOTSXP) {
      SEXP x = obj;
      response->set_totalcount(obj.length());
      int i = 0;
      while (x != R_NilValue && i < reqEnd) {
        if (i >= reqStart) {
          VariablesResponse::Variable* var = response->add_vars();
          if (TAG(x) != R_NilValue) {
            std::string name = asStringUTF8(PRINTNAME(TAG(x)));
            trim(name);
            var->set_name(name);
          }
          getValueInfo(CAR(x), var->mutable_value());
        }
        x = CDR(x);
        ++i;
      }
      return;
    }
    if (obj.type() != VECSXP && obj.type() != INTSXP && obj.type() != REALSXP && obj.type() != STRSXP &&
        obj.type() != RAWSXP && obj.type() != CPLXSXP && obj.type() != LGLSXP && obj.type() != EXPRSXP) {
      return;
    }
    R_xlen_t length = obj.length();
    response->set_totalcount(length);
    ShieldSEXP unclassed = Rf_inherits(obj, "factor") ? (SEXP)obj : RI->unclass(obj);
    ShieldSEXP filtered = RI->subscript(unclassed, RI->colon(reqStart + 1, std::min(length, reqEnd)));
    ShieldSEXP names = Rf_getAttrib(filtered, R_NamesSymbol);
    for (int i = 0; i < filtered.length(); ++i) {
      VariablesResponse::Variable* var = response->add_vars();
      std::string name = stringEltUTF8(names, i);
      trim(name);
      var->set_name(name);
      getValueInfo(RI->doubleSubscript(filtered, i + 1), var->mutable_value());
    }
  }, context, true);
  return Status::OK;
}