22 #define COMPILING_RCPP
24 #include <sys/types.h>
46 namespace attributes {
57 path_ = as<std::string>(fileInfo[
"path"]);
58 exists_ = as<bool>(fileInfo[
"exists"]);
65 fileInfo[
"path"] =
path_;
76 std::string::size_type pos =
path_.find_last_of(
'.');
77 if (pos != std::string::npos)
78 return path_.substr(pos);
94 return ! (*
this == other);
130 bool isQuoted(
const std::string& str);
133 bool endsWith(
const std::string& str,
const std::string& suffix);
150 namespace attributes {
188 return !(*
this == other);
194 if(
isConst() ) res +=
"const " ;
230 return !(*
this == other);
249 const std::string&
name,
263 return name().find_first_of(
'.') == 0;
275 return !(*
this == other);
292 explicit Param(
const std::string& paramText);
301 return !(*
this == other);
318 const std::vector<Param>&
params,
320 const std::vector<std::string>&
roxygen)
335 return !(*
this == other);
365 return params()[0].name();
369 return function().
name();
375 std::replace(
name.begin(),
name.end(),
'.',
'_');
381 if (!rngParam.
empty())
390 if (!invisibleParam.
empty())
401 std::string sig = sigParam.
value();
403 if (sig.empty())
return sig;
404 #if __cplusplus < 201103L
405 if (sig[sig.size() - 1] ==
'}')
407 if (sig.back() ==
'}')
409 sig = sig.substr(0, sig.size()-1);
411 if (sig.empty())
return sig;
412 #if __cplusplus < 201103L
415 if (sig.front() ==
'{')
447 virtual const std::vector<std::string>&
modules()
const = 0;
449 virtual const std::vector<std::vector<std::string> >&
roxygenChunks()
const = 0;
467 namespace attributes {
489 const std::string& packageFile,
490 bool parseDependencies);
505 virtual const std::vector<std::string>&
modules()
const
510 virtual const std::vector<std::vector<std::string> >&
roxygenChunks()
const {
525 return it->hasParameter(name);
565 const std::string& attribute,
596 namespace attributes {
603 const std::string& commentPrefix);
625 virtual bool commit(
const std::vector<std::string>& includes) = 0;
631 operator std::ostream&() {
648 return "RcppExport_validate";
660 bool commit(
const std::string& preamble = std::string());
682 return "10BE3573-1514-4C36-9D1C-5A225CD40393";
700 const std::string& fileSep);
703 virtual void writeEnd(
bool hasPackageInit);
704 virtual bool commit(
const std::vector<std::string>& includes);
711 const std::string& exportedName,
712 const std::string& name)
const;
733 const std::string& fileSep);
736 virtual void writeEnd(
bool hasPackageInit);
737 virtual bool commit(
const std::vector<std::string>& includes);
742 std::string
getCCallable(
const std::string&
function)
const;
754 const std::string& fileSep);
757 virtual void writeEnd(
bool hasPackageInit);
758 virtual bool commit(
const std::vector<std::string>& includes);
775 const std::string& fileSep);
778 virtual void writeEnd(
bool hasPackageInit);
779 virtual bool commit(
const std::vector<std::string>& includes);
792 typedef std::vector<ExportsGenerator*>::iterator
Itr;
805 std::vector<std::string>
commit(
806 const std::vector<std::string>& includes);
809 std::vector<std::string>
remove();
830 bool includePrototype,
832 const std::string& contextId);
843 namespace attributes {
848 const std::string& regex)
854 Rcpp::List matches = regmatches(lines, result);
858 template <
typename Stream>
859 void readFile(
const std::string& file, Stream& os) {
860 std::ifstream ifs(file.c_str());
867 template <
typename Collection>
868 void readLines(std::istream&
is, Collection* pLines) {
871 while(std::getline(
is, line)) {
873 if (line.length() > 0 && *line.rbegin() ==
'\r')
874 line.erase(line.length()-1, 1);
876 pLines->push_back(line);
881 std::vector<FileInfo>* pDependencies) {
884 std::string path = Rcpp::as<std::string>(include);
885 for (
size_t i = 0; i<pDependencies->size(); ++i) {
886 if (pDependencies->at(i).path() == path)
891 pDependencies->push_back(
FileInfo(path));
895 void parseSourceDependencies(
const std::string& sourceFile,
896 std::vector<FileInfo>* pDependencies) {
912 std::stringstream buffer;
913 readFile(sourceFile, buffer);
918 std::deque<std::string> lines;
919 readLines(buffer, &lines);
924 linesVector,
"^\\s*#include\\s*\"([^\"]+)\"\\s*$");
928 std::vector<FileInfo> newDependencies;
929 for (
int i = 0; i<matches.
size(); i++) {
930 std::string line = lines[i];
938 filepath(sourceDir, std::string(
match[1]));
942 include = normalizePath(include,
"/");
943 if (addUniqueDependency(include, pDependencies)) {
944 newDependencies.push_back(
945 FileInfo(Rcpp::as<std::string>(include)));
948 std::vector<std::string> exts;
949 exts.push_back(
".cc");
950 exts.push_back(
".cpp");
951 for (
size_t i = 0; i<exts.size(); ++i) {
954 std::string file = Rcpp::as<std::string>(
955 filePathSansExt(include)) + exts[i];
957 exists = fileExists(file);
959 if (addUniqueDependency(file,
962 newDependencies.push_back(fileInfo);
972 for (
size_t i = 0; i<newDependencies.size(); i++) {
973 FileInfo dependency = newDependencies[i];
974 parseSourceDependencies(dependency.
path(), pDependencies);
979 std::vector<FileInfo> parseSourceDependencies(
980 std::string sourceFile) {
985 sourceFile = Rcpp::as<std::string>(normalizePath(sourceFile,
"/"));
988 std::vector<FileInfo> dependencies;
989 parseSourceDependencies(sourceFile, &dependencies);
992 dependencies.erase(
std::remove(dependencies.begin(),
1003 std::vector<std::string> parseEmbeddedR(
1005 const std::deque<std::string>& lines) {
1006 Rcpp::List matches = regexMatches(linesVector,
1007 "^\\s*/\\*{3,}\\s*[Rr]\\s*$");
1008 bool withinRBlock =
false;
1010 std::vector<std::string> embeddedR;
1012 for (
int i = 0; i<matches.
size(); i++) {
1015 std::string line = lines[i];
1024 withinRBlock =
true;
1026 else if (withinRBlock) {
1028 embeddedR.push_back(line);
1030 withinRBlock =
false;
1044 std::ostringstream ostr;
1046 ostr <<
type() <<
"(*" <<
name <<
")(";
1048 const std::vector<Argument>& args =
arguments();
1049 for (std::size_t i = 0; i<args.size(); i++) {
1050 ostr << args[i].type();
1051 if (i != (args.size()-1))
1064 std::string::size_type pos = paramText.find(
"=") ;
1065 if ( pos != std::string::npos ) {
1067 name_ = paramText.substr(0, pos);
1070 value_ = paramText.substr(pos + 1) ;
1083 for (std::vector<Param>::const_iterator
1085 if (it->name() ==
name)
1093 if (!type.
empty()) {
1106 bool printDefault =
true) {
1107 if (!argument.
empty()) {
1108 os << argument.
type();
1109 if (!argument.
name().empty()) {
1111 os << argument.
name();
1127 bool printArgDefaults =
true) {
1129 if (!
function.empty()) {
1130 if (!
function.type().empty()) {
1131 os <<
function.type();
1134 os <<
function.name();
1136 const std::vector<Argument>& arguments =
function.arguments();
1137 for (std::size_t i = 0; i<arguments.size(); i++) {
1139 if (i != (arguments.size()-1))
1154 if (!param.
empty()) {
1156 if (!param.
value().empty())
1157 os <<
"=" << param.
value();
1164 if (!attribute.
empty()) {
1165 os <<
"[[Rcpp::" << attribute.
name();
1166 const std::vector<Param>& params = attribute.
params();
1167 if (params.size() > 0) {
1169 for (std::size_t i = 0; i<params.size(); i++) {
1171 if (i != (params.size()-1))
1186 const std::string& sourceFile,
1187 const std::string& packageName,
1188 bool parseDependencies)
1189 : sourceFile_(sourceFile), hasPackageInit_(false)
1193 std::string packageNameCpp = packageName;
1194 std::replace(packageNameCpp.begin(), packageNameCpp.end(),
'.',
'_');
1199 std::stringstream buffer;
1200 readFile(sourceFile_, buffer);
1201 std::string contents = buffer.str();
1204 if (contents.find(
"[[Rcpp::") != std::string::npos ||
1205 contents.find(
"RCPP_MODULE") != std::string::npos ||
1206 contents.find(
"R_init_" + packageNameCpp) != std::string::npos) {
1211 std::deque<std::string> lines;
1212 readLines(buffer, &lines);
1218 "^\\s*//\\s*\\[\\[Rcpp::(\\w+)(\\(.*?\\))?\\]\\]\\s*$");
1219 for (
int i = 0; i<matches.
size(); i++) {
1222 std::string line = lines[i];
1241 attributes_.push_back(attr);
1249 if (line.find(
"//'") == 0) {
1250 std::string roxLine =
"#" + line.substr(2);
1251 roxygenBuffer_.push_back(roxLine);
1255 else if (!roxygenBuffer_.empty()) {
1256 roxygenChunks_.push_back(roxygenBuffer_);
1257 roxygenBuffer_.clear();
1263 commentState.
reset();
1265 "^\\s*RCPP_MODULE\\s*\\(\\s*(\\w+)\\s*\\).*$");
1266 for (
int i = 0; i<modMatches.
size(); i++) {
1269 std::string line = lines[i];
1277 const char * name =
match[1];
1283 hasPackageInit_ =
false;
1284 commentState.
reset();
1285 std::string pkgInit =
"R_init_" + packageNameCpp;
1286 Rcpp::List initMatches = regexMatches(lines_,
"^[^/]+" + pkgInit +
".*DllInfo.*$");
1287 for (
int i = 0; i<initMatches.
size(); i++) {
1290 std::string line = lines[i];
1298 hasPackageInit_ =
true;
1304 embeddedR_ = parseEmbeddedR(lines_, lines);
1307 if (parseDependencies) {
1310 sourceDependencies_ = parseSourceDependencies(sourceFile);
1313 for (
size_t i = 0; i<sourceDependencies_.size(); i++) {
1316 std::string dependency = sourceDependencies_[i].path();
1321 it = parser.begin(); it != parser.end(); ++it) {
1324 *it) == attributes_.end()) {
1325 attributes_.push_back(*it);
1330 std::copy(parser.modules().begin(),
1331 parser.modules().end(),
1332 std::back_inserter(modules_));
1339 Attribute SourceFileAttributesParser::parseAttribute(
1340 const std::vector<std::string>&
match,
1343 std::string name =
match[1];
1346 if (!isKnownAttribute(name)) {
1347 attributeWarning(
"Unrecognized attribute Rcpp::" + name,
1352 std::vector<Param> params;
1353 std::string paramsText =
match[2];
1354 if (!paramsText.empty()) {
1361 paramsText = paramsText.substr(1, paramsText.size()-2);
1364 params = parseParameters(paramsText);
1376 if ((lineNumber + 1) < lines_.size())
1377 function = parseFunction(lineNumber + 1);
1379 rcppExportWarning(
"No function found", lineNumber);
1382 for (std::size_t i=0; i<params.size(); i++) {
1384 std::string name = params[i].name();
1385 std::string value = params[i].value();
1388 if (value.empty() && (i > 0)) {
1389 rcppExportWarning(
"No value specified for parameter '" +
1394 else if (!value.empty() &&
1399 rcppExportWarning(
"Unrecognized parameter '" + name +
"'",
1408 rcppExportWarning(
"rng value must be true or false",
1418 rcppExportWarning(
"invisible value must be true or false",
1427 if (params.empty()) {
1428 rcppInterfacesWarning(
"No interfaces specified", lineNumber);
1431 for (std::size_t i=0; i<params.size(); i++) {
1432 std::string param = params[i].name();
1434 rcppInterfacesWarning(
1435 "Unknown interface '" + param +
"'", lineNumber);
1445 roxygenBuffer_.clear();
1450 std::vector<Param> SourceFileAttributesParser::parseParameters(
1451 const std::string& input) {
1453 std::string::size_type blockend = input.find_last_of(
kParamBlockEnd);
1455 const std::string delimiters(
",");
1456 std::vector<Param> params;
1457 std::string::size_type current;
1458 std::string::size_type next = std::string::npos;
1459 std::string::size_type signature_param_start = std::string::npos;
1461 next = input.find_first_not_of(delimiters, next + 1);
1462 if (next == std::string::npos)
1466 next = input.find_first_of(delimiters, next + 1);
1467 }
while((next >= blockstart) && (next <= blockend) &&
1468 (next != std::string::npos));
1469 params.push_back(
Param(input.substr(current, next - current)));
1471 signature_param_start = current;
1473 }
while(next != std::string::npos);
1477 if(signature_param_start != std::string::npos) {
1479 signature_param_start < blockstart &&
1480 blockstart < blockend &&
1481 blockstart != std::string::npos &&
1482 blockend != std::string::npos;
1491 Function SourceFileAttributesParser::parseFunction(
size_t lineNumber) {
1494 std::string signature = parseSignature(lineNumber);
1495 if (signature.empty()) {
1496 rcppExportNoFunctionFoundWarning(lineNumber);
1502 std::string::size_type endParenLoc = signature.find_last_of(
')');
1503 std::string::size_type beginParenLoc = signature.find_first_of(
'(');
1504 if (endParenLoc == std::string::npos ||
1505 beginParenLoc == std::string::npos ||
1506 endParenLoc < beginParenLoc) {
1508 rcppExportNoFunctionFoundWarning(lineNumber);
1516 const std::string preambleText = signature.substr(0, beginParenLoc);
1517 for (std::string::const_reverse_iterator
1518 it = preambleText.rbegin(); it != preambleText.rend(); ++it) {
1521 if (!name.empty()) {
1524 std::string typeText;
1525 while (++it != preambleText.rend())
1526 typeText.insert(0U, 1U, *it);
1527 type = parseType(typeText);
1535 name.insert(0U, 1U, ch);
1541 rcppExportNoFunctionFoundWarning(lineNumber);
1547 rcppExportWarning(
"No function return type found", lineNumber);
1552 std::vector<Argument> arguments;
1553 std::string argsText = signature.substr(beginParenLoc + 1,
1554 endParenLoc-beginParenLoc-1);
1555 std::vector<std::string> args = parseArguments(argsText);
1556 for (std::vector<std::string>::const_iterator it =
1557 args.begin(); it != args.end(); ++it) {
1560 std::string arg = *it;
1568 std::string defaultValue;
1569 std::string::size_type eqPos = arg.find_first_of(
'=');
1570 if ( (eqPos != std::string::npos) && ((eqPos + 1) < arg.size()) ) {
1571 defaultValue = arg.substr(eqPos+1);
1573 arg = arg.substr(0, eqPos);
1588 if (pos != std::string::npos) {
1590 std::string::size_type ref_pos = arg.substr(pos).find_last_of(
"&");
1591 if (ref_pos != std::string::npos) {
1593 arg.insert(pos,
" ");
1596 name = arg.substr(pos);
1600 rcppExportInvalidParameterWarning(arg, lineNumber);
1605 Type type = parseType(arg.substr(0, pos));
1607 rcppExportInvalidParameterWarning(arg, lineNumber);
1612 arguments.push_back(
Argument(name, type, defaultValue));
1615 return Function(type, name, arguments);
1620 std::string SourceFileAttributesParser::parseSignature(
size_t lineNumber) {
1624 std::string signature;
1625 for (
int i = lineNumber; i<lines_.size(); i++) {
1628 bool insideQuotes =
false;
1631 for (
size_t c = 0; c < line.length(); ++c) {
1633 char ch = line.at(c);
1635 if (ch ==
'"' && prevChar !=
'\\')
1636 insideQuotes = !insideQuotes;
1638 if (!insideQuotes && ((ch ==
'{') || (ch ==
';'))) {
1639 signature.append(line.substr(0, c));
1648 signature.append(line);
1649 signature.push_back(
' ');
1653 return std::string();
1660 std::vector<std::string> SourceFileAttributesParser::parseArguments(
1661 const std::string& argText) {
1663 int templateCount = 0;
1665 std::string currentArg;
1666 std::vector<std::string> args;
1668 bool escaped =
false;
1669 typedef std::string::const_iterator it_t;
1670 for (it_t it = argText.begin(); it != argText.end(); ++it) {
1676 if ( ! quote && (ch ==
'"' || ch ==
'\''))
1678 else if (quote && ch == quote && ! escaped)
1684 else if (quote && ch ==
'\\')
1690 (templateCount == 0) &&
1691 (parenCount == 0)) {
1692 args.push_back(currentArg);
1698 if ( ! currentArg.empty() || ch !=
' ')
1699 currentArg.push_back(ch);
1720 if (!currentArg.empty())
1721 args.push_back(currentArg);
1726 Type SourceFileAttributesParser::parseType(
const std::string& text) {
1728 const std::string constQualifier(
"const");
1729 const std::string referenceQualifier(
"&");
1732 std::string type = text;
1736 bool isConst =
false;
1737 bool isReference =
false;
1738 if (type.find(constQualifier) == 0) {
1740 type.erase(0, constQualifier.length());
1748 if (type.find(referenceQualifier) ==
1749 (type.length() - referenceQualifier.length())) {
1751 type.erase(type.length() - referenceQualifier.length());
1759 return Type(type, isConst, isReference);
1764 bool SourceFileAttributesParser::isKnownAttribute(
const std::string& name)
1774 void SourceFileAttributesParser::attributeWarning(
1776 const std::string& attribute,
1777 size_t lineNumber) {
1781 std::string file = Rcpp::as<std::string>(basename(sourceFile_));
1783 std::ostringstream ostr;
1785 if (!attribute.empty())
1786 ostr <<
" for " << attribute <<
" attribute";
1787 ostr <<
" at " << file <<
":" << lineNumber;
1792 void SourceFileAttributesParser::attributeWarning(
1794 size_t lineNumber) {
1795 attributeWarning(
message,
"", lineNumber);
1798 void SourceFileAttributesParser::rcppExportWarning(
1800 size_t lineNumber) {
1801 attributeWarning(
message,
"Rcpp::export", lineNumber);
1804 void SourceFileAttributesParser::rcppExportNoFunctionFoundWarning(
1805 size_t lineNumber) {
1806 rcppExportWarning(
"No function found", lineNumber);
1809 void SourceFileAttributesParser::rcppExportInvalidParameterWarning(
1810 const std::string& param,
1811 size_t lineNumber) {
1812 rcppExportWarning(
"Invalid parameter: "
1813 "'" + param +
"'", lineNumber);
1816 void SourceFileAttributesParser::rcppInterfacesWarning(
1818 size_t lineNumber) {
1819 attributeWarning(
message +
" (valid interfaces are 'r' and 'cpp')",
1820 "Rcpp::interfaces", lineNumber);
1825 void CommentState::submitLine(
const std::string& line) {
1826 std::size_t pos = 0;
1827 while (pos != std::string::npos) {
1830 std::size_t lineCommentPos = line.find(
"//", pos);
1833 std::string token = inComment() ?
"*/" :
"/*";
1834 pos = line.find(token, pos);
1837 if (pos != std::string::npos) {
1840 if (lineCommentPos != std::string::npos && lineCommentPos < pos)
1843 inComment_ = !inComment_;
1844 pos += token.size();
1858 namespace attributes {
1862 const char *
const kRcppExportsSuffix =
"_RcppExports.h";
1863 const char *
const kTrySuffix =
"_try";
1867 const std::string& package,
1868 const std::string& commentPrefix)
1869 : targetFile_(targetFile),
1871 packageCpp_(package),
1872 commentPrefix_(commentPrefix),
1873 hasCppInterface_(false) {
1880 std::stringstream buffer;
1881 buffer << ifs.rdbuf();
1916 std::ostringstream headerStream;
1918 <<
"Rcpp::compileAttributes()"
1919 <<
" -> do not edit by hand" << std::endl;
1922 if (!preamble.empty())
1923 headerStream << preamble;
1926 std::string generatedCode = headerStream.str() + code;
1930 std::ofstream::out | std::ofstream::trunc);
1935 ofs << generatedCode;
1951 std::string newname(name);
1952 std::replace(newname.begin(), newname.end(),
'.',
'_');
1957 const std::string& package,
1958 const std::string& fileSep)
1960 packageDir + fileSep +
"src" + fileSep +
"RcppExports.cpp",
1982 it = attributes.
begin(); it != attributes.
end(); ++it) {
1984 if (it->isExportedFunction()) {
2002 const std::vector<std::string>& modules = attributes.
modules();
2009 for (std::vector<Attribute>::const_iterator
2010 it = attributes.
begin(); it != attributes.
end(); ++it) {
2011 if (it->isExportedFunction())
2012 Rcpp::Rcout <<
" " << it->function() << std::endl;
2026 ostr() << std::endl;
2027 ostr() <<
"// validate"
2028 <<
" (ensure exported C++ functions exist before "
2029 <<
"calling them)" << std::endl;
2031 <<
"(const char* sig) { " << std::endl;
2032 ostr() <<
" static std::set<std::string> signatures;"
2034 ostr() <<
" if (signatures.empty()) {" << std::endl;
2038 ostr() <<
" signatures.insert(\""
2040 <<
"\");" << std::endl;
2042 ostr() <<
" }" << std::endl;
2043 ostr() <<
" return signatures.find(sig) != signatures.end();"
2045 ostr() <<
"}" << std::endl;
2049 ostr() << std::endl;
2050 ostr() <<
"// registerCCallable (register entry points for "
2051 "exported C++ functions)" << std::endl;
2053 <<
"() { " << std::endl;
2060 ostr() << std::endl;
2065 ostr() << std::endl;
2066 ostr() <<
" return R_NilValue;" << std::endl;
2067 ostr() <<
"}" << std::endl;
2074 std::vector<std::string> routineNames;
2075 std::vector<std::size_t> routineArgs;
2081 std::string kRcppModuleBoot =
"_rcpp_module_boot_";
2082 for (std::size_t i=0;i<
modules_.size(); i++) {
2083 routineNames.push_back(kRcppModuleBoot +
modules_[i]);
2084 routineArgs.push_back(0);
2088 routineArgs.push_back(0);
2093 List extraRoutines = extraRoutinesFunc(
targetFile(), routineNames);
2094 std::vector<std::string> declarations = extraRoutines[
"declarations"];
2095 std::vector<std::string>
callEntries = extraRoutines[
"call_entries"];
2098 for (std::size_t i=0;i<
modules_.size(); i++) {
2099 declarations.
push_back(
"RcppExport SEXP " + kRcppModuleBoot +
modules_[i] +
"();");
2103 if (declarations.size() > 0) {
2104 ostr() << std::endl;
2105 for (std::size_t i = 0; i<declarations.size(); i++)
2106 ostr() << declarations[i] << std::endl;
2110 ostr() << std::endl;
2111 ostr() <<
"static const R_CallMethodDef CallEntries[] = {" << std::endl;
2112 for (std::size_t i=0;i<routineNames.size(); i++) {
2113 ostr() <<
" {\"" << routineNames[i] <<
"\", " <<
2114 "(DL_FUNC) &" << routineNames[i] <<
", " <<
2115 routineArgs[i] <<
"}," << std::endl;
2118 for (std::size_t i = 0; i<
callEntries.size(); i++)
2121 ostr() <<
" {NULL, NULL, 0}" << std::endl;
2122 ostr() <<
"};" << std::endl;
2124 ostr() << std::endl;
2130 ostr() <<
";" << std::endl;
2133 ostr() <<
"RcppExport void R_init_" <<
packageCpp() <<
"(DllInfo *dll) {" << std::endl;
2134 ostr() <<
" R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);" << std::endl;
2135 ostr() <<
" R_useDynamicSymbols(dll, FALSE);" << std::endl;
2139 ostr() <<
" " <<
function.name() <<
"(dll);" << std::endl;
2141 ostr() <<
"}" << std::endl;
2146 showWarning(
"[[Rcpp::init]] attribute used in a package with an explicit "
2147 "R_init function (Rcpp::init functions will not be called)");
2153 const std::string& exportedName,
2154 const std::string& name)
const {
2155 std::ostringstream
ostr;
2156 std::string indentStr(indent,
' ');
2157 ostr << indentStr <<
"R_RegisterCCallable(\"" <<
package() <<
"\", "
2166 std::ostringstream
ostr;
2167 if (!includes.empty()) {
2168 for (std::size_t i=0;i<includes.size(); i++)
2169 ostr << includes[i] << std::endl;
2172 ostr <<
"#include <string>" << std::endl;
2173 ostr <<
"#include <set>" << std::endl;
2178 ostr <<
"using namespace Rcpp;" << std::endl << std::endl;
2187 const std::string& packageDir,
2188 const std::string& package,
2189 const std::string& fileSep)
2191 packageDir + fileSep +
"inst" + fileSep +
"include" +
2192 fileSep + dotNameHelper(package) + kRcppExportsSuffix,
2196 includeDir_ = packageDir + fileSep +
"inst" + fileSep +
"include";
2202 << std::endl << std::endl;
2210 ostr() <<
" using namespace Rcpp;" << std::endl << std::endl;
2215 ostr() <<
" namespace {" << std::endl;
2216 ostr() <<
" void validateSignature(const char* sig) {"
2218 ostr() <<
" Rcpp::Function require = "
2219 <<
"Rcpp::Environment::base_env()[\"require\"];"
2222 <<
"Rcpp::Named(\"quietly\") = true);"
2225 std::string validate =
"validate";
2226 std::string fnType =
"Ptr_" + validate;
2227 ostr() <<
" typedef int(*" << fnType <<
")(const char*);"
2230 std::string ptrName =
"p_" + validate;
2231 ostr() <<
" static " << fnType <<
" " << ptrName <<
" = "
2232 <<
"(" << fnType <<
")" << std::endl
2235 <<
";" << std::endl;
2236 ostr() <<
" if (!" << ptrName <<
"(sig)) {" << std::endl;
2237 ostr() <<
" throw Rcpp::function_not_exported("
2240 <<
"\"C++ function with signature '\" + std::string(sig) + \"' not found in " <<
package()
2241 <<
"\");" << std::endl;
2242 ostr() <<
" }" << std::endl;
2243 ostr() <<
" }" << std::endl;
2245 ostr() <<
" }" << std::endl << std::endl;
2256 for(std::vector<Attribute>::const_iterator
2257 it = attributes.
begin(); it != attributes.
end(); ++it) {
2259 if (it->isExportedFunction()) {
2262 it->function().
renamedTo(it->exportedCppName());
2265 if (
function.isHidden())
2268 ostr() <<
" inline " <<
function <<
" {"
2271 std::string fnType =
"Ptr_" +
function.name();
2272 ostr() <<
" typedef SEXP(*" << fnType <<
")(";
2273 for (
size_t i=0; i<
function.arguments().size(); i++) {
2275 if (i != (
function.arguments().size()-1))
2278 ostr() <<
");" << std::endl;
2280 std::string ptrName =
"p_" +
function.name();
2281 ostr() <<
" static " << fnType <<
" "
2282 << ptrName <<
" = NULL;"
2284 ostr() <<
" if (" << ptrName <<
" == NULL) {"
2286 ostr() <<
" validateSignature"
2287 <<
"(\"" <<
function.signature() <<
"\");"
2289 ostr() <<
" " << ptrName <<
" = "
2290 <<
"(" << fnType <<
")"
2293 ostr() <<
" }" << std::endl;
2294 ostr() <<
" RObject rcpp_result_gen;" << std::endl;
2295 ostr() <<
" {" << std::endl;
2297 ostr() <<
" RNGScope RCPP_rngScope_gen;" << std::endl;
2298 ostr() <<
" rcpp_result_gen = " << ptrName <<
"(";
2300 const std::vector<Argument>& args =
function.arguments();
2301 for (std::size_t i = 0; i<args.size(); i++) {
2302 ostr() <<
"Shield<SEXP>(Rcpp::wrap(" << args[i].name() <<
"))";
2303 if (i != (args.size()-1))
2307 ostr() <<
");" << std::endl;
2308 ostr() <<
" }" << std::endl;
2310 ostr() <<
" if (rcpp_result_gen.inherits(\"interrupted-error\"))"
2312 <<
" throw Rcpp::internal::InterruptedException();"
2314 ostr() <<
" if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))"
2316 <<
" throw Rcpp::LongjumpException(rcpp_result_gen);"
2318 ostr() <<
" if (rcpp_result_gen.inherits(\"try-error\"))"
2320 <<
" throw Rcpp::exception(Rcpp::as<std::string>("
2321 <<
"rcpp_result_gen).c_str());"
2323 if (!
function.type().isVoid()) {
2324 ostr() <<
" return Rcpp::as<" <<
function.type() <<
" >"
2325 <<
"(rcpp_result_gen);" << std::endl;
2328 ostr() <<
" }" << std::endl << std::endl;
2334 ostr() <<
"}" << std::endl;
2335 ostr() << std::endl;
2340 const std::vector<std::string>& includes) {
2348 std::ostringstream
ostr;
2352 ostr <<
"#ifndef " << guard << std::endl;
2353 ostr <<
"#define " << guard << std::endl << std::endl;
2356 if (!includes.empty()) {
2357 for (std::size_t i=0;i<includes.size(); i++)
2362 std::string preamble =
"#include \"../inst/include/";
2363 std::string pkgInclude = preamble +
packageCpp() +
".h\"";
2364 if (includes[i] == pkgInclude)
2368 std::string typesInclude = preamble +
packageCpp() +
"_types.h";
2369 if (includes[i].
find(typesInclude) != std::string::npos)
2371 std::string include =
"#include \"" +
2372 includes[i].substr(preamble.length());
2373 ostr << include << std::endl;
2377 ostr << includes[i] << std::endl;
2392 const std::string&
function)
const {
2393 std::ostringstream
ostr;
2394 ostr <<
"R_GetCCallable"
2395 <<
"(\"" <<
package() <<
"\", "
2396 <<
"\"" <<
function <<
"\")";
2401 return "RCPP_" +
packageCpp() +
"_RCPPEXPORTS_H_GEN_";
2405 const std::string& packageDir,
2406 const std::string& package,
2407 const std::string& fileSep)
2409 packageDir + fileSep +
"inst" + fileSep +
"include" +
2410 fileSep + dotNameHelper(package) +
".h",
2414 includeDir_ = packageDir + fileSep +
"inst" + fileSep +
"include";
2421 ostr() <<
"#ifndef " << guard << std::endl;
2422 ostr() <<
"#define " << guard << std::endl << std::endl;
2424 <<
"\"" << std::endl;
2426 ostr() << std::endl;
2450 const std::string& package,
2452 const std::string& fileSep)
2454 packageDir + fileSep +
"R" + fileSep +
"RcppExports.R",
2457 registration_(registration)
2465 const std::vector<std::vector<std::string> >& roxygenChunks =
2467 for (std::size_t i = 0; i<roxygenChunks.size(); i++) {
2468 const std::vector<std::string>& chunk = roxygenChunks[i];
2469 for (std::size_t l = 0; l < chunk.size(); l++)
2470 ostr() << chunk[l] << std::endl;
2471 ostr() <<
"NULL" << std::endl << std::endl;
2477 for(std::vector<Attribute>::const_iterator
2478 it = attributes.
begin(); it != attributes.
end(); ++it) {
2487 for (
size_t i=0; i<attribute.
roxygen().size(); i++)
2496 std::string rsig_err_msg =
"Missing args in " + args;
2504 bool isInvisibleOrVoid =
function.type().isVoid() || attribute.
invisible();
2507 ostr() << name <<
" <- function(" << args <<
") {"
2510 if (isInvisibleOrVoid)
2511 ostr() <<
"invisible(";
2519 ostr() <<
"', " <<
"PACKAGE = '" <<
package() <<
"'";
2524 const std::vector<Argument>& arguments =
function.arguments();
2525 for (
size_t i = 0; i<arguments.size(); i++)
2526 ostr() <<
", " << arguments[i].name();
2528 if (isInvisibleOrVoid)
2530 ostr() << std::endl;
2532 ostr() <<
"}" << std::endl << std::endl;
2540 ostr() <<
"# Register entry points for exported C++ functions"
2542 ostr() <<
"methods::setLoadAction(function(ns) {" << std::endl;
2544 <<
"', PACKAGE = '" <<
package() <<
"')"
2545 << std::endl <<
"})" << std::endl;
2568 (*it)->writeBegin();
2575 (*it)->writeFunctions(attributes, verbose);
2580 (*it)->writeEnd(hasPackageInit);
2585 const std::vector<std::string>& includes) {
2587 std::vector<std::string> updated;
2590 if ((*it)->commit(includes))
2591 updated.push_back((*it)->targetFile());
2599 std::vector<std::string> removed;
2601 if ((*it)->remove())
2602 removed.push_back((*it)->targetFile());
2613 std::string cppNumericArgToRArg(
const std::string& type,
2614 const std::string& cppArg) {
2617 std::stringstream argStream(cppArg);
2618 if ((argStream >> num)) {
2621 if (!argStream.eof()) {
2623 argStream >> suffix;
2624 if (argStream.eof() && suffix ==
"L")
2630 if (cppArg.find(
'.') == std::string::npos &&
2631 type !=
"double" && type !=
"float")
2632 return cppArg +
"L";
2639 return std::string();
2645 std::string cppCreateArgToRArg(
const std::string& cppArg) {
2647 std::string create =
"::create";
2648 size_t createLoc = cppArg.find(create);
2649 if (createLoc == std::string::npos ||
2650 ((createLoc + create.length()) >= cppArg.size())) {
2651 return std::string();
2654 std::string type = cppArg.substr(0, createLoc);
2655 std::string rcppScope =
"Rcpp::";
2656 size_t rcppLoc = type.find(rcppScope);
2657 if (rcppLoc == 0 && type.size() > rcppScope.length())
2658 type = type.substr(rcppScope.length());
2660 std::string args = cppArg.substr(createLoc + create.length());
2661 if (type ==
"CharacterVector")
2662 return "as.character( c" + args +
")";
2663 if (type ==
"IntegerVector")
2664 return "as.integer( c" + args +
")";
2665 if (type ==
"NumericVector")
2666 return "as.numeric( c" + args +
")";
2667 if (type ==
"LogicalVector")
2668 return "as.logical( c" + args +
")";
2670 return std::string();
2675 std::string cppMatrixArgToRArg(
const std::string& cppArg) {
2678 std::string matrix =
"Matrix";
2679 size_t matrixLoc = cppArg.find(matrix);
2680 if (matrixLoc == std::string::npos ||
2681 ((matrixLoc + matrix.length()) >= cppArg.size())) {
2682 return std::string();
2685 std::string args = cppArg.substr(matrixLoc + matrix.length());
2686 return "matrix" + args;
2691 std::string cppLiteralArgToRArg(
const std::string& cppArg) {
2692 if (cppArg ==
"true")
2694 else if (cppArg ==
"false")
2696 else if (cppArg ==
"R_NilValue")
2698 else if (cppArg ==
"NA_STRING")
2699 return "NA_character_";
2700 else if (cppArg ==
"NA_INTEGER")
2701 return "NA_integer_";
2702 else if (cppArg ==
"NA_LOGICAL")
2703 return "NA_integer_";
2704 else if (cppArg ==
"NA_REAL")
2707 return std::string();
2712 std::string cppConstructorArgToRArg(
const std::string& cppArg) {
2715 static std::map<std::string, std::string> RcppContainerToR;
2716 RcppContainerToR.insert(std::make_pair(
"NumericVector",
"numeric"));
2717 RcppContainerToR.insert(std::make_pair(
"DoubleVector",
"numeric"));
2718 RcppContainerToR.insert(std::make_pair(
"CharacterVector",
"character"));
2719 RcppContainerToR.insert(std::make_pair(
"IntegerVector",
"integer"));
2720 RcppContainerToR.insert(std::make_pair(
"LogicalVector",
"logical"));
2721 RcppContainerToR.insert(std::make_pair(
"ComplexVector",
"complex"));
2725 typedef std::map<std::string, std::string>::const_iterator Iterator;
2726 for (Iterator it = RcppContainerToR.begin(); it != RcppContainerToR.end(); ++it) {
2727 size_t loc = cppArg.find(it->first);
2728 if (loc != std::string::npos) {
2729 return it->second + cppArg.substr(it->first.size(), std::string::npos);
2733 return std::string();
2739 std::string cppArgToRArg(
const std::string& type,
2740 const std::string& cppArg) {
2747 std::string rArg = cppLiteralArgToRArg(cppArg);
2752 rArg = cppCreateArgToRArg(cppArg);
2757 rArg = cppMatrixArgToRArg(cppArg);
2762 rArg = cppNumericArgToRArg(type, cppArg);
2767 rArg = cppConstructorArgToRArg(cppArg);
2772 return std::string();
2779 std::ostringstream argsOstr;
2780 const std::vector<Argument>& arguments =
function.arguments();
2781 for (
size_t i = 0; i<arguments.size(); i++) {
2782 const Argument& argument = arguments[i];
2783 argsOstr << argument.
name();
2785 std::string rArg = cppArgToRArg(argument.
type().
name(),
2787 if (!rArg.empty()) {
2788 argsOstr <<
" = " << rArg;
2790 showWarning(
"Unable to parse C++ default value '" +
2792 argument.
name() +
" of function " +
2797 if (i != (arguments.size()-1))
2800 return argsOstr.str();
2805 std::vector<std::string> required_args;
2806 const std::vector<Argument>& arguments =
function.arguments();
2807 for (
size_t i = 0; i<arguments.size(); i++) {
2808 const Argument& argument = arguments[i];
2809 required_args.push_back(argument.
name());
2811 args =
"function(" + args +
") {}";
2820 std::vector<std::string> parsed_args =
2821 Rcpp::as<std::vector<std::string> >(pargs_cv);
2823 for(
size_t i=0; i<required_args.size(); ++i) {
2824 if(
std::find(parsed_args.begin(), parsed_args.end(),
2825 required_args[i]) == parsed_args.end())
2833 ostr <<
"#ifdef RCPP_USE_GLOBAL_ROSTREAM" << std::endl;
2834 ostr <<
"Rcpp::Rostream<true>& Rcpp::Rcout = Rcpp::Rcpp_cout_get();";
2836 ostr <<
"Rcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();";
2838 ostr <<
"#endif" << std::endl << std::endl;
2845 bool includePrototype,
2847 const std::string& contextId) {
2850 for(std::vector<Attribute>::const_iterator
2851 it = attributes.
begin(); it != attributes.
end(); ++it) {
2860 if (includePrototype) {
2861 ostr <<
"// " <<
function.
name() << std::endl;
2869 ostr << (cppInterface ?
"static" :
"RcppExport");
2871 std::string funcName = contextId +
"_" +
function.name();
2876 std::ostringstream ostrArgs;
2877 const std::vector<Argument>& arguments =
function.arguments();
2878 for (
size_t i = 0; i<arguments.size(); i++) {
2879 const Argument& argument = arguments[i];
2880 ostrArgs <<
"SEXP " << argument.
name() <<
"SEXP";
2881 if (i != (arguments.size()-1))
2884 std::string args = ostrArgs.str();
2885 ostr << args <<
") {" << std::endl;
2886 ostr <<
"BEGIN_RCPP" << std::endl;
2887 if (!
function.type().isVoid())
2888 ostr <<
" Rcpp::RObject rcpp_result_gen;" << std::endl;
2889 if (!cppInterface && attribute.
rng())
2890 ostr <<
" Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
2891 for (
size_t i = 0; i<arguments.size(); i++) {
2892 const Argument& argument = arguments[i];
2894 ostr <<
" Rcpp::traits::input_parameter< "
2896 <<
"(" << argument.
name() <<
"SEXP);" << std::endl;
2900 if (!
function.type().isVoid())
2901 ostr <<
"rcpp_result_gen = Rcpp::wrap(";
2902 ostr <<
function.name() <<
"(";
2903 for (
size_t i = 0; i<arguments.size(); i++) {
2904 const Argument& argument = arguments[i];
2905 ostr << argument.
name();
2906 if (i != (arguments.size()-1))
2909 if (!
function.type().isVoid())
2911 ostr <<
");" << std::endl;
2913 if (!
function.type().isVoid())
2915 ostr <<
" return rcpp_result_gen;" << std::endl;
2919 ostr <<
" return R_NilValue;" << std::endl;
2921 ostr << (cppInterface ?
"END_RCPP_RETURN_ERROR" :
"END_RCPP")
2923 ostr <<
"}" << std::endl;
2927 ostr <<
"RcppExport SEXP " << funcName <<
"(" << args <<
") {"
2929 ostr <<
" SEXP rcpp_result_gen;" << std::endl;
2930 ostr <<
" {" << std::endl;
2931 if (attribute.
rng())
2932 ostr <<
" Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
2933 ostr <<
" rcpp_result_gen = PROTECT(" << funcName
2934 << kTrySuffix <<
"(";
2935 for (
size_t i = 0; i<arguments.size(); i++) {
2936 const Argument& argument = arguments[i];
2937 ostr << argument.
name() <<
"SEXP";
2938 if (i != (arguments.size()-1))
2941 ostr <<
"));" << std::endl;
2942 ostr <<
" }" << std::endl;
2943 ostr <<
" Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, \"interrupted-error\");"
2945 <<
" if (rcpp_isInterrupt_gen) {" << std::endl
2946 <<
" UNPROTECT(1);" << std::endl
2947 <<
" Rf_onintr();" << std::endl
2948 <<
" }" << std::endl
2949 <<
" bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);" << std::endl
2950 <<
" if (rcpp_isLongjump_gen) {" << std::endl
2952 <<
" Rcpp::internal::resumeJump(rcpp_result_gen);" << std::endl
2953 <<
" }" << std::endl
2954 <<
" Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"try-error\");"
2956 <<
" if (rcpp_isError_gen) {" << std::endl
2957 <<
" SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);" << std::endl
2958 <<
" UNPROTECT(1);" << std::endl
2959 <<
" Rf_error(CHAR(rcpp_msgSEXP_gen));" << std::endl
2960 <<
" }" << std::endl
2961 <<
" UNPROTECT(1);" << std::endl
2962 <<
" return rcpp_result_gen;" << std::endl
2963 <<
"}" << std::endl;
2977 namespace attributes {
2981 : path_(path), exists_(false), lastModified_(0)
2984 struct _stat buffer;
2991 if (errno == ENOENT)
3033 if (pStr->empty())
return;
3035 size_t len = pStr->length();
3036 bool inString =
false;
3044 if (idx == std::string::npos)
return;
3047 if (idx + 1 < len && pStr->at(idx) ==
'/' && pStr->at(idx + 1) ==
'/') {
3052 while (idx < len - 1) {
3055 if (pStr->at(idx) ==
'"' && pStr->at(idx - 1) !=
'\\') {
3059 if (pStr->at(idx) ==
'"') {
3065 pStr->at(idx) ==
'/' &&
3066 pStr->at(idx + 1) ==
'/') {
3083 if (pos != std::string::npos)
3084 pStr->erase(pos + 1);
3088 pStr->erase(0, pos);
3093 if (pStr->length() < 2)
3095 char quote = *(pStr->begin());
3096 if ( (quote ==
'\'' || quote ==
'\"') && (*(pStr->rbegin()) == quote) )
3097 *pStr = pStr->substr(1, pStr->length()-2);
3102 if (str.length() < 2)
3104 char quote = *(str.begin());
3105 return (quote ==
'\'' || quote ==
'\"') && (*(str.rbegin()) == quote);
3109 bool endsWith(
const std::string& str,
const std::string& suffix)
3111 return str.size() >= suffix.size() &&
3112 str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
3122 size_t len = str.length();
3123 if (len < 3)
return false;
3125 if (idx == std::string::npos)
return false;
3128 if (len - 2 < idx)
return false;
3130 if (str[idx] ==
'/' &&
3131 str[idx + 1] ==
'/' &&
3132 str[idx + 2] ==
'\'') {
3154 class SourceCppDynlib {
3156 SourceCppDynlib() {}
3158 SourceCppDynlib(
const std::string& cacheDir,
3159 const std::string& cppSourcePath,
3161 : cppSourcePath_(cppSourcePath)
3165 FileInfo cppSourceFilenameInfo(cppSourcePath_);
3166 if (!cppSourceFilenameInfo.exists())
3171 cppSourceFilename_ = Rcpp::as<std::string>(basename(cppSourcePath_));
3174 fileSep_ = Rcpp::as<std::string>(platform[
"file.sep"]);
3175 dynlibExt_ = Rcpp::as<std::string>(platform[
"dynlib.ext"]);
3179 buildDirectory_ = Rcpp::as<std::string>(tempfile(
"sourcecpp_", cacheDir));
3180 std::replace(buildDirectory_.begin(), buildDirectory_.end(),
'\\',
'/');
3182 dircreate(buildDirectory_);
3185 contextId_ =
"sourceCpp_" + uniqueToken(cacheDir);
3188 regenerateSource(cacheDir);
3192 explicit SourceCppDynlib(
const Rcpp::List& dynlib)
3194 using namespace Rcpp;
3196 cppSourcePath_ = as<std::string>(dynlib[
"cppSourcePath"]);
3197 generatedCpp_ = as<std::string>(dynlib[
"generatedCpp"]);
3198 cppSourceFilename_ = as<std::string>(dynlib[
"cppSourceFilename"]);
3199 contextId_ = as<std::string>(dynlib[
"contextId"]);
3200 buildDirectory_ = as<std::string>(dynlib[
"buildDirectory"]);
3201 fileSep_ = as<std::string>(dynlib[
"fileSep"]);
3202 dynlibFilename_ = as<std::string>(dynlib[
"dynlibFilename"]);
3203 previousDynlibFilename_ = as<std::string>(dynlib[
"previousDynlibFilename"]);
3204 dynlibExt_ = as<std::string>(dynlib[
"dynlibExt"]);
3205 exportedFunctions_ = as<std::vector<std::string> >(dynlib[
"exportedFunctions"]);
3206 modules_ = as<std::vector<std::string> >(dynlib[
"modules"]);
3207 depends_ = as<std::vector<std::string> >(dynlib[
"depends"]);
3208 plugins_ = as<std::vector<std::string> >(dynlib[
"plugins"]);
3209 embeddedR_ = as<std::vector<std::string> >(dynlib[
"embeddedR"]);
3210 List sourceDependencies = as<List>(dynlib[
"sourceDependencies"]);
3211 for (R_xlen_t i = 0; i<sourceDependencies.length(); i++) {
3212 List fileInfo = as<List>(sourceDependencies.at(i));
3213 sourceDependencies_.push_back(
FileInfo(fileInfo));
3219 using namespace Rcpp;
3221 dynlib[
"cppSourcePath"] = cppSourcePath_;
3222 dynlib[
"generatedCpp"] = generatedCpp_;
3223 dynlib[
"cppSourceFilename"] = cppSourceFilename_;
3224 dynlib[
"contextId"] = contextId_;
3225 dynlib[
"buildDirectory"] = buildDirectory_;
3226 dynlib[
"fileSep"] = fileSep_;
3227 dynlib[
"dynlibFilename"] = dynlibFilename_;
3228 dynlib[
"previousDynlibFilename"] = previousDynlibFilename_;
3229 dynlib[
"dynlibExt"] = dynlibExt_;
3230 dynlib[
"exportedFunctions"] = exportedFunctions_;
3231 dynlib[
"modules"] = modules_;
3232 dynlib[
"depends"] = depends_;
3233 dynlib[
"plugins"] = plugins_;
3234 dynlib[
"embeddedR"] = embeddedR_;
3235 List sourceDependencies;
3236 for (std::size_t i = 0; i<sourceDependencies_.size(); i++) {
3237 FileInfo fileInfo = sourceDependencies_.
at(i);
3240 dynlib[
"sourceDependencies"] = sourceDependencies;
3245 bool isEmpty()
const {
return cppSourcePath_.empty(); }
3247 bool isBuilt()
const {
return FileInfo(dynlibPath()).
exists(); };
3249 bool isSourceDirty()
const {
3251 if (
FileInfo(cppSourcePath_).lastModified() >
3252 FileInfo(generatedCppSourcePath()).lastModified())
3260 std::vector<FileInfo> sourceDependencies = parseSourceDependencies(
3262 if (sourceDependencies != sourceDependencies_)
3269 void regenerateSource(
const std::string& cacheDir) {
3272 previousDynlibFilename_ = dynlibFilename_;
3273 dynlibFilename_ =
"sourceCpp_" + uniqueToken(cacheDir) + dynlibExt_;
3277 filecopy(cppSourcePath_, generatedCppSourcePath(),
true);
3283 std::ostringstream ostr;
3285 ostr << std::endl << std::endl;
3286 ostr <<
"#include <Rcpp.h>" << std::endl;
3289 generateCpp(ostr, sourceAttributes,
true,
false, contextId_);
3290 generatedCpp_ = ostr.str();
3291 std::ofstream cppOfs(generatedCppSourcePath().c_str(),
3292 std::ofstream::out | std::ofstream::app);
3295 cppOfs << generatedCpp_;
3299 std::ofstream rOfs(generatedRSourcePath().c_str(),
3300 std::ofstream::out | std::ofstream::trunc);
3305 std::string dllInfo =
"`." + contextId_ +
"_DLLInfo`";
3306 rOfs << dllInfo <<
" <- dyn.load('" << dynlibPath() <<
"')"
3307 << std::endl << std::endl;
3310 generateR(rOfs, sourceAttributes, dllInfo);
3313 rOfs << std::endl <<
"rm(" << dllInfo <<
")"
3319 exportedFunctions_.clear();
3323 it = sourceAttributes.begin(); it != sourceAttributes.end(); ++it) {
3326 exportedFunctions_.push_back(it->exportedName());
3329 for (
size_t i = 0; i<it->params().size(); ++i)
3330 depends_.push_back(it->params()[i].name());
3334 for (
size_t i = 0; i<it->params().size(); ++i)
3335 plugins_.push_back(it->params()[i].name());
3340 modules_ = sourceAttributes.modules();
3343 embeddedR_ = sourceAttributes.embeddedR();
3346 sourceDependencies_ = sourceAttributes.sourceDependencies();
3349 const std::string& contextId()
const {
3353 const std::string& cppSourcePath()
const {
3354 return cppSourcePath_;
3357 const std::vector<std::string> cppDependencySourcePaths() {
3358 std::vector<std::string> dependencies;
3359 for (
size_t i = 0; i<sourceDependencies_.size(); ++i) {
3360 FileInfo dep = sourceDependencies_[i];
3362 dependencies.push_back(dep.
path());
3365 return dependencies;
3368 std::string buildDirectory()
const {
3369 return buildDirectory_;
3372 std::string generatedCpp()
const {
3373 return generatedCpp_;
3376 std::string cppSourceFilename()
const {
3377 return cppSourceFilename_;
3380 std::string rSourceFilename()
const {
3381 return cppSourceFilename() +
".R";
3384 std::string dynlibFilename()
const {
3385 return dynlibFilename_;
3388 std::string dynlibPath()
const {
3389 return buildDirectory_ + fileSep_ + dynlibFilename();
3392 std::string previousDynlibPath()
const {
3393 if (!previousDynlibFilename_.empty())
3394 return buildDirectory_ + fileSep_ + previousDynlibFilename_;
3396 return std::string();
3399 const std::vector<std::string>& exportedFunctions()
const {
3400 return exportedFunctions_;
3403 const std::vector<std::string>& modules()
const {
3407 const std::vector<std::string>& depends()
const {
return depends_; };
3409 const std::vector<std::string>& plugins()
const {
return plugins_; };
3411 const std::vector<std::string>& embeddedR()
const {
return embeddedR_; }
3415 std::string generatedCppSourcePath()
const {
3416 return buildDirectory_ + fileSep_ + cppSourceFilename();
3419 std::string generatedRSourcePath()
const {
3420 return buildDirectory_ + fileSep_ + rSourceFilename();
3423 void generateR(std::ostream& ostr,
3425 const std::string& dllInfo)
const
3428 for(std::vector<Attribute>::const_iterator
3429 it = attributes.
begin(); it != attributes.
end(); ++it) {
3444 std::string rsig_err_msg =
"Missing args in " + args;
3451 <<
" <- Rcpp:::sourceCppFunction("
3452 <<
"function(" << args <<
") {}, "
3453 << (
function.type().isVoid() ?
"TRUE" :
"FALSE") <<
", "
3455 <<
"'" << contextId_ +
"_" +
function.name()
3456 <<
"')" << std::endl;
3460 std::vector<std::string> modules = attributes.
modules();
3461 if (modules.size() > 0)
3464 ostr <<
"library(Rcpp)" << std::endl;
3467 for (std::vector<std::string>::const_iterator
3468 it = modules.begin(); it != modules.end(); ++it)
3470 ostr <<
" populate( Rcpp::Module(\"" << *it <<
"\","
3471 << dllInfo <<
"), environment() ) " << std::endl;
3477 std::string uniqueToken(
const std::string& cacheDir) {
3479 Rcpp::Function uniqueTokenFunc = rcppEnv[
".sourceCppDynlibUniqueToken"];
3480 return Rcpp::as<std::string>(uniqueTokenFunc(cacheDir));
3484 std::string cppSourcePath_;
3485 std::string generatedCpp_;
3486 std::string cppSourceFilename_;
3487 std::string contextId_;
3488 std::string buildDirectory_;
3489 std::string fileSep_;
3490 std::string dynlibFilename_;
3491 std::string previousDynlibFilename_;
3492 std::string dynlibExt_;
3493 std::vector<std::string> exportedFunctions_;
3494 std::vector<std::string> modules_;
3495 std::vector<std::string> depends_;
3496 std::vector<std::string> plugins_;
3497 std::vector<std::string> embeddedR_;
3498 std::vector<FileInfo> sourceDependencies_;
3503 void dynlibCacheInsert(
const std::string& cacheDir,
3504 const std::string& file,
3505 const std::string& code,
3506 const SourceCppDynlib& dynlib)
3509 Rcpp::Function dynlibInsertFunc = rcppEnv[
".sourceCppDynlibInsert"];
3510 dynlibInsertFunc(cacheDir, file, code, dynlib.toList());
3513 void dynlibCacheInsertFile(
const std::string& cacheDir,
3514 const std::string& file,
3515 const SourceCppDynlib& dynlib)
3517 dynlibCacheInsert(cacheDir, file,
"", dynlib);
3520 void dynlibCacheInsertCode(
const std::string& cacheDir,
3521 const std::string& code,
3522 const SourceCppDynlib& dynlib)
3524 dynlibCacheInsert(cacheDir,
"", code, dynlib);
3527 SourceCppDynlib dynlibCacheLookup(
const std::string& cacheDir,
3528 const std::string& file,
3529 const std::string& code)
3532 Rcpp::Function dynlibLookupFunc = rcppEnv[
".sourceCppDynlibLookup"];
3533 Rcpp::List dynlibList = dynlibLookupFunc(cacheDir, file, code);
3534 if (dynlibList.
length() > 0)
3535 return SourceCppDynlib(dynlibList);
3537 return SourceCppDynlib();
3540 SourceCppDynlib dynlibCacheLookupByFile(
const std::string& cacheDir,
3541 const std::string& file)
3543 return dynlibCacheLookup(cacheDir, file,
"");
3546 SourceCppDynlib dynlibCacheLookupByCode(
const std::string& cacheDir,
3547 const std::string& code)
3549 return dynlibCacheLookup(cacheDir,
"", code);
3557 SEXP sRebuild, SEXP sCacheDir, SEXP sPlatform) {
3560 std::string file = Rcpp::as<std::string>(sFile);
3561 std::string code = sCode != R_NilValue ? Rcpp::as<std::string>(sCode) :
"";
3562 bool rebuild = Rcpp::as<bool>(sRebuild);
3563 std::string cacheDir = Rcpp::as<std::string>(sCacheDir);
3564 Rcpp::List platform = Rcpp::as<Rcpp::List>(sPlatform);
3567 SourceCppDynlib dynlib = !code.empty() ? dynlibCacheLookupByCode(cacheDir, code)
3568 : dynlibCacheLookupByFile(cacheDir, file);
3571 bool buildRequired =
false;
3574 if (dynlib.isEmpty()) {
3575 buildRequired =
true;
3576 dynlib = SourceCppDynlib(cacheDir, file, platform);
3580 else if (rebuild || dynlib.isSourceDirty()) {
3581 buildRequired =
true;
3582 dynlib.regenerateSource(cacheDir);
3586 else if (!dynlib.isBuilt()) {
3587 buildRequired =
true;
3592 dynlibCacheInsertCode(cacheDir, code, dynlib);
3594 dynlibCacheInsertFile(cacheDir, file, dynlib);
3597 using namespace Rcpp;
3599 _[
"contextId"] = dynlib.contextId(),
3600 _[
"cppSourcePath"] = dynlib.cppSourcePath(),
3601 _[
"cppDependencySourcePaths"] = dynlib.cppDependencySourcePaths(),
3602 _[
"buildRequired"] = buildRequired,
3603 _[
"buildDirectory"] = dynlib.buildDirectory(),
3604 _[
"generatedCpp"] = dynlib.generatedCpp(),
3605 _[
"exportedFunctions"] = dynlib.exportedFunctions(),
3606 _[
"modules"] = dynlib.modules(),
3607 _[
"cppSourceFilename"] = dynlib.cppSourceFilename(),
3608 _[
"rSourceFilename"] = dynlib.rSourceFilename(),
3609 _[
"dynlibFilename"] = dynlib.dynlibFilename(),
3610 _[
"dynlibPath"] = dynlib.dynlibPath(),
3611 _[
"previousDynlibPath"] = dynlib.previousDynlibPath(),
3612 _[
"depends"] = dynlib.depends(),
3613 _[
"plugins"] = dynlib.plugins(),
3614 _[
"embeddedR"] = dynlib.embeddedR());
3625 SEXP sCppFileBasenames,
3631 std::string packageDir = Rcpp::as<std::string>(sPackageDir);
3632 std::string packageName = Rcpp::as<std::string>(sPackageName);
3635 std::set<std::string> depends;
3637 it = vDepends.
begin(); it != vDepends.
end(); ++it) {
3638 depends.insert(std::string(*it));
3641 bool registration = Rcpp::as<bool>(sRegistration);
3643 std::vector<std::string> cppFiles =
3644 Rcpp::as<std::vector<std::string> >(sCppFiles);
3645 std::vector<std::string> cppFileBasenames =
3646 Rcpp::as<std::vector<std::string> >(sCppFileBasenames);
3647 std::vector<std::string> includes =
3648 Rcpp::as<std::vector<std::string> >(sIncludes);
3649 bool verbose = Rcpp::as<bool>(sVerbose);
3650 Rcpp::List platform = Rcpp::as<Rcpp::List>(sPlatform);
3651 std::string fileSep = Rcpp::as<std::string>(platform[
"file.sep"]);
3667 "The header file '" + e.
filePath() +
"' already exists so "
3668 "cannot be overwritten by Rcpp::interfaces";
3685 bool hasPackageInit =
false;
3686 bool haveAttributes =
false;
3687 std::set<std::string> dependsAttribs;
3688 for (std::size_t i=0; i<cppFiles.size(); i++) {
3691 std::string cppFile = cppFiles[i];
3692 if (
endsWith(cppFile,
"RcppExports.cpp"))
3700 hasPackageInit =
true;
3707 haveAttributes =
true;
3714 it = attributes.
begin(); it != attributes.
end(); ++it) {
3716 for (
size_t i = 0; i<it->params().size(); ++i)
3717 dependsAttribs.insert(it->params()[i].name());
3723 generators.
writeEnd(hasPackageInit);
3726 std::vector<std::string> updated;
3728 updated = generators.
commit(includes);
3730 updated = generators.
remove();
3734 std::vector<std::string>
diff;
3735 std::set_difference(dependsAttribs.begin(), dependsAttribs.end(),
3736 depends.begin(), depends.end(),
3737 std::back_inserter(
diff));
3738 if (!
diff.empty()) {
3740 "The following packages are referenced using Rcpp::depends "
3741 "attributes however are not listed in the Depends, Imports or "
3742 "LinkingTo fields of the package DESCRIPTION file: ";
3743 for (
size_t i=0; i<
diff.size(); i++) {
3745 if (i != (
diff.size()-1))
3753 for (
size_t i=0; i<updated.size(); i++)
3754 Rcpp::Rcout << updated[i] <<
" updated." << std::endl;
3758 return Rcpp::wrap<std::vector<std::string> >(updated);
RcppExport SEXP compileAttributes(SEXP sPackageDir, SEXP sPackageName, SEXP sDepends, SEXP sRegistration, SEXP sCppFiles, SEXP sCppFileBasenames, SEXP sIncludes, SEXP sVerbose, SEXP sPlatform)
RcppExport SEXP sourceCppContext(SEXP sFile, SEXP sCode, SEXP sRebuild, SEXP sCacheDir, SEXP sPlatform)
traits::r_vector_iterator< RTYPE, PreserveStorage >::type iterator
void push_back(const T &object)
Proxy at(const size_t &i)
Argument(const std::string &name, const Type &type, const std::string &defaultValue)
bool operator!=(const Argument &other) const
std::string defaultValue_
const std::string & defaultValue() const
bool operator==(const Argument &other) const
const Type & type() const
const std::string & name() const
std::vector< Param > params_
std::vector< std::string > roxygen_
bool hasParameter(const std::string &name) const
const std::vector< std::string > & roxygen() const
const std::string & name() const
bool operator!=(const Attribute &other) const
const Function & function() const
std::string exportedCppName() const
std::string exportedName() const
bool operator==(const Attribute &other) const
std::string customRSignature() const
Param paramNamed(const std::string &name) const
const std::vector< Param > & params() const
Attribute(const std::string &name, const std::vector< Param > ¶ms, const Function &function, const std::vector< std::string > &roxygen)
bool isExportedFunction() const
std::string registerCCallable(size_t indent, const std::string &exportedName, const std::string &name) const
std::vector< Attribute > initFunctions_
virtual bool commit(const std::vector< std::string > &includes)
virtual void doWriteFunctions(const SourceFileAttributes &attributes, bool verbose)
CppExportsGenerator(const std::string &packageDir, const std::string &package, const std::string &fileSep)
virtual void writeBegin()
std::vector< std::string > modules_
std::vector< Attribute > nativeRoutines_
std::vector< Attribute > cppExports_
virtual void writeEnd(bool hasPackageInit)
virtual void writeBegin()
CppExportsIncludeGenerator(const std::string &packageDir, const std::string &package, const std::string &fileSep)
virtual void writeEnd(bool hasPackageInit)
virtual void doWriteFunctions(const SourceFileAttributes &attributes, bool verbose)
std::string getHeaderGuard() const
std::string getCCallable(const std::string &function) const
virtual bool commit(const std::vector< std::string > &includes)
virtual void doWriteFunctions(const SourceFileAttributes &, bool)
virtual void writeEnd(bool hasPackageInit)
virtual bool commit(const std::vector< std::string > &includes)
virtual void writeBegin()
std::string getHeaderGuard() const
CppPackageIncludeGenerator(const std::string &packageDir, const std::string &package, const std::string &fileSep)
bool hasCppInterface() const
ExportsGenerator(const ExportsGenerator &)
virtual void doWriteFunctions(const SourceFileAttributes &attributes, bool verbose)=0
std::string exportValidationFunction()
void writeFunctions(const SourceFileAttributes &attributes, bool verbose)
std::string generatorToken() const
const std::string & package() const
virtual bool commit(const std::vector< std::string > &includes)=0
std::string registerCCallableExportedName()
std::string exportValidationFunctionRegisteredName()
std::string existingCode_
const std::string packageCppPrefix() const
std::string commentPrefix_
virtual void writeEnd(bool hasPackageInit)=0
std::string dotNameHelper(const std::string &name) const
virtual ~ExportsGenerator()
bool isSafeToOverwrite() const
ExportsGenerator & operator=(const ExportsGenerator &)
std::ostringstream codeStream_
const std::string & packageCpp() const
const std::string & targetFile() const
virtual void writeBegin()=0
ExportsGenerator(const std::string &targetFile, const std::string &package, const std::string &commentPrefix)
ExportsGenerators(const ExportsGenerators &)
void writeEnd(bool hasPackageInit)
void add(ExportsGenerator *pGenerator)
std::vector< ExportsGenerator * >::iterator Itr
std::vector< std::string > remove()
virtual ~ExportsGenerators()
void writeFunctions(const SourceFileAttributes &attributes, bool verbose)
std::vector< ExportsGenerator * > generators_
ExportsGenerators & operator=(const ExportsGenerators &)
std::vector< std::string > commit(const std::vector< std::string > &includes)
std::string extension() const
FileInfo(const std::string &path)
bool operator<(const FileInfo &other) const
FileInfo(const List &fileInfo)
double lastModified() const
std::ostream & operator<<(std::ostream &os) const
bool operator==(const FileInfo &other) const
bool operator!=(const FileInfo &other) const
const std::string & name() const
std::string signature() const
bool operator==(const Function &other) const
const Type & type() const
const std::vector< Argument > & arguments() const
Function(const Type &type, const std::string &name, const std::vector< Argument > &arguments)
Function renamedTo(const std::string &name) const
bool operator!=(const Function &other) const
std::vector< Argument > arguments_
const std::string & value() const
bool operator!=(const Param &other) const
bool operator==(const Param &other) const
const std::string & name() const
virtual void writeEnd(bool hasPackageInit)
virtual void doWriteFunctions(const SourceFileAttributes &attributes, bool verbose)
virtual void writeBegin()
RExportsGenerator(const std::string &packageDir, const std::string &package, bool registration, const std::string &fileSep)
virtual bool commit(const std::vector< std::string > &includes)
std::vector< std::string > parseArguments(const std::string &argText)
std::string parseSignature(size_t lineNumber)
std::vector< std::vector< std::string > > roxygenChunks_
bool isKnownAttribute(const std::string &name) const
void attributeWarning(const std::string &message, const std::string &attribute, size_t lineNumber)
SourceFileAttributesParser & operator=(const SourceFileAttributesParser &)
void rcppInterfacesWarning(const std::string &message, size_t lineNumber)
SourceFileAttributesParser(const std::string &sourceFile, const std::string &packageFile, bool parseDependencies)
virtual bool hasInterface(const std::string &name) const
virtual const std::string & sourceFile() const
void rcppExportNoFunctionFoundWarning(size_t lineNumber)
virtual const_iterator begin() const
std::vector< std::string > roxygenBuffer_
const std::vector< FileInfo > & sourceDependencies() const
virtual const std::vector< std::vector< std::string > > & roxygenChunks() const
Function parseFunction(size_t lineNumber)
virtual const std::vector< std::string > & modules() const
std::vector< std::string > modules_
Type parseType(const std::string &text)
virtual const_iterator end() const
std::vector< std::string > embeddedR_
std::vector< Param > parseParameters(const std::string &input)
virtual bool hasGeneratorOutput() const
const std::vector< std::string > & embeddedR() const
SourceFileAttributesParser(const SourceFileAttributesParser &)
std::vector< FileInfo > sourceDependencies_
void attributeWarning(const std::string &message, size_t lineNumber)
void rcppExportWarning(const std::string &message, size_t lineNumber)
Attribute parseAttribute(const std::vector< std::string > &match, int lineNumber)
bool hasPackageInit() const
std::vector< Attribute > attributes_
void rcppExportInvalidParameterWarning(const std::string ¶m, size_t lineNumber)
virtual const_iterator end() const =0
std::vector< Attribute >::const_iterator const_iterator
virtual const std::string & sourceFile() const =0
virtual bool hasGeneratorOutput() const =0
virtual bool hasPackageInit() const =0
virtual const_iterator begin() const =0
virtual const std::vector< std::vector< std::string > > & roxygenChunks() const =0
virtual ~SourceFileAttributes()
virtual const std::vector< std::string > & modules() const =0
virtual bool hasInterface(const std::string &name) const =0
bool operator!=(const Type &other) const
Type(const std::string &name, bool isConst, bool isReference)
const std::string & name() const
bool operator==(const Type &other) const
std::string full_name() const
std::string filePath() const
const char *const kParamValueTRUE
void initializeGlobals(std::ostream &ostr)
void stripQuotes(std::string *pStr)
const char *const kInitAttribute
const char *const kParamValueFalse
const char *const kExportInvisible
const char *const kExportRng
void printArgument(std::ostream &os, const Argument &argument, bool printDefault=true)
bool isQuoted(const std::string &str)
const char *const kWhitespaceChars
bool endsWith(const std::string &str, const std::string &suffix)
const char *const kInterfaceR
void printFunction(std::ostream &os, const Function &function, bool printArgDefaults=true)
std::ostream & operator<<(std::ostream &os, const Type &type)
const char *const kInterfaceCpp
const char *const kDependsAttribute
const char *const kPluginsAttribute
bool isWhitespace(char ch)
void showWarning(const std::string &msg)
const char *const kParamValueTrue
bool isRoxygenCpp(const std::string &str)
const char *const kExportName
void trimWhitespace(std::string *pStr)
std::string generateRArgList(const Function &function)
bool checkRSignature(const Function &function, std::string args)
const char *const kParamValueFALSE
const char *const kExportSignature
void stripTrailingLineComments(std::string *pStr)
const char *const kInterfacesAttribute
const char *const kParamBlockEnd
const char *const kExportAttribute
bool removeFile(const std::string &path)
void generateCpp(std::ostream &ostr, const SourceFileAttributes &attributes, bool includePrototype, bool cppInterface, const std::string &contextId)
void createDirectory(const std::string &path)
const char *const kParamBlockStart
Function_Impl< PreserveStorage > Function
bool remove(const std::string &name)
void warning(const char *fmt, Args &&... args)
Argument Named(const std::string &name)
Vector< LGLSXP > LogicalVector
SEXP find(const std::string &name) const
RObject_Impl< PreserveStorage > RObject
static Environment_Impl base_env()
sugar::Diff< INTSXP, LHS_NA, LHS_T > diff(const VectorBase< INTSXP, LHS_NA, LHS_T > &lhs)
static internal::NamedPlaceHolder _
static Environment_Impl namespace_env(const std::string &package)
static Rostream< true > Rcout
IntegerVector match(const VectorBase< RTYPE, NA, T > &x, const VectorBase< RTYPE, RHS_NA, RHS_T > &table_)
Environment_Impl< PreserveStorage > Environment
bool exists(const std::string &name) const
SEXP wrap(const Date &date)
static R_CallMethodDef callEntries[]