in src/RLoader.cpp [35:176]
void getValueInfo(SEXP _var, ValueInfo* result) {
ShieldSEXP var = _var;
try {
auto type = var.type();
if (type == PROMSXP) {
if (PRVALUE(var) == R_UnboundValue) {
TextBuilder builder;
builder.build(PRCODE(var));
std::string code = builder.getText();
trim(code);
result->mutable_unevaluated()->set_code(code);
return;
}
getValueInfo(PRVALUE(var), result);
return;
}
ShieldSEXP classes = RI->classes(Rf_lang2(RI->quote, var));
if (classes.type() == STRSXP) {
int length = 0;
for (int i = 0; i < classes.length(); ++i) {
std::string s = stringEltUTF8(classes, i);
if (s.empty()) continue;
length += s.size();
if (s.size() > MAX_PREVIEW_CLS_LENGTH) break;
result->add_cls(s);
}
}
if (type == LANGSXP || type == SYMSXP) {
result->mutable_value()->set_isvector(false);
TextBuilder builder;
builder.build(var);
std::string s = builder.getText();
result->mutable_value()->set_iscomplete(trim(s));
result->mutable_value()->set_textvalue(s);
} else if (type == DOTSXP) {
result->mutable_list()->set_length(var.length());
} else if (type == CLOSXP || type == SPECIALSXP || type == BUILTINSXP) {
std::string header = getFunctionHeader(var);
if (header.size() <= MAX_PREVIEW_STRING_LENGTH) {
result->mutable_function()->set_header(header);
} else {
header = getFunctionHeaderShort(var);
if (header.size() <= MAX_PREVIEW_STRING_LENGTH) {
result->mutable_function()->set_header(header);
} else {
result->mutable_function()->set_header("function(...)");
}
}
} else if (type == ENVSXP) {
std::string name = asStringUTF8(RI->environmentName(var));
trim(name);
result->mutable_environment()->set_name(name);
} else if (type == BCODESXP || type == WEAKREFSXP || type == EXTPTRSXP) {
result->mutable_value()->set_isvector(false);
bool trimmed;
std::string value = getPrintedValueWithLimit(RI->unclass(Rf_lang2(RI->quote, var)), MAX_PREVIEW_STRING_LENGTH, trimmed);
result->mutable_value()->set_textvalue(value);
result->mutable_value()->set_iscomplete(!trimmed);
} else if (type == CHARSXP) {
getValueInfo(Rf_ScalarString(var), result);
} else if (Rf_inherits(var, "ggplot")) {
result->mutable_graph();
} else if (Rf_inherits(var, "data.frame")) {
ValueInfo::DataFrame* dataFrame = result->mutable_dataframe();
dataFrame->set_rows(asInt(RI->nrow(var)));
dataFrame->set_cols(asInt(RI->ncol(var)));
} else if (type == S4SXP) {
result->mutable_value()->set_iss4(true);
} else {
if (Rf_isVector(var)) {
ShieldSEXP dim = Rf_getAttrib(var, R_DimSymbol);
if (dim.type() == INTSXP && dim.length() >= 2) {
int length = std::min<int>(dim.length(), MAX_PREVIEW_PRINTED_COUNT);
for (int i = 0; i < length; ++i) {
result->mutable_matrix()->add_dim(asInt(dim[i]));
}
return;
}
}
if (type == VECSXP || type == LISTSXP || type == EXPRSXP) {
result->mutable_list()->set_length(var.length());
} else {
ValueInfo::Value *value = result->mutable_value();
if (type == LGLSXP || type == INTSXP || type == REALSXP ||
type == CPLXSXP || type == NILSXP) {
R_xlen_t length = var.length();
value->set_isvector(length > 1);
PrSEXP x = Rf_inherits(var, "factor") ? (SEXP)var : RI->unclass(var);
bool isComplete = true;
if (length > MAX_PREVIEW_PRINTED_COUNT) {
isComplete = false;
x = RI->subscript(x, RI->colon(1, MAX_PREVIEW_PRINTED_COUNT));
}
bool trimmed;
std::string s;
if (Rf_inherits(x, "factor")) {
s = evalAndGetPrintedValueWithLimit(
RI->printFactorSimple.lang(x),
MAX_PREVIEW_STRING_LENGTH, trimmed);
} else {
s = getPrintedValueWithLimit(x, MAX_PREVIEW_STRING_LENGTH, trimmed);
}
value->set_textvalue(s);
value->set_iscomplete(isComplete && !trimmed);
} else if (type == STRSXP) {
int length = var.length();
value->set_isvector(length > 1);
bool isComplete = length <= MAX_PREVIEW_PRINTED_COUNT;
ShieldSEXP unclassed = RI->unclass(var);
ShieldSEXP vector =
isComplete
? (SEXP)unclassed
: RI->subscript(unclassed, RI->colon(1, MAX_PREVIEW_PRINTED_COUNT));
ShieldSEXP vectorPrefix =
RI->substring(vector, 1, MAX_PREVIEW_STRING_LENGTH);
ShieldSEXP nchar = RI->nchar(vectorPrefix);
for (int i = 0; isComplete && i < vectorPrefix.length(); ++i) {
if (!vectorPrefix.isNA(i) &&
asInt(nchar[i]) == MAX_PREVIEW_STRING_LENGTH) {
isComplete = false;
}
}
bool trimmed;
value->set_textvalue(getPrintedValueWithLimit(vectorPrefix, MAX_PREVIEW_STRING_LENGTH, trimmed));
value->set_iscomplete(isComplete && !trimmed);
} else {
value->set_isvector(false);
value->set_textvalue("");
value->set_iscomplete(true);
}
}
}
} catch (RInterruptedException const& e) {
result->mutable_error()->set_text(e.what());
throw;
} catch (RExceptionBase const& e) {
result->mutable_error()->set_text(e.what());
} catch (...) {
result->mutable_error()->set_text("Error");
throw;
}
}