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);
150namespace 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();
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 (sig.back() ==
'}')
405 sig = sig.substr(0, sig.size()-1);
407 if (sig.empty())
return sig;
408 if (sig.front() ==
'{')
439 virtual const std::vector<std::string>&
modules()
const = 0;
441 virtual const std::vector<std::vector<std::string> >&
roxygenChunks()
const = 0;
459namespace attributes {
481 const std::string& packageFile,
482 bool parseDependencies);
497 virtual const std::vector<std::string>&
modules()
const
502 virtual const std::vector<std::vector<std::string> >&
roxygenChunks()
const {
517 return it->hasParameter(name);
551 std::vector<std::string>
parseArguments(
const std::string& argText);
557 const std::string& attribute,
588namespace attributes {
595 const std::string& commentPrefix);
617 virtual bool commit(
const std::vector<std::string>& includes) = 0;
623 operator std::ostream&() {
640 return "RcppExport_validate";
652 bool commit(
const std::string& preamble = std::string());
674 return "10BE3573-1514-4C36-9D1C-5A225CD40393";
692 const std::string& fileSep);
695 virtual void writeEnd(
bool hasPackageInit);
696 virtual bool commit(
const std::vector<std::string>& includes);
703 const std::string& exportedName,
704 const std::string& name)
const;
725 const std::string& fileSep);
728 virtual void writeEnd(
bool hasPackageInit);
729 virtual bool commit(
const std::vector<std::string>& includes);
746 const std::string& fileSep);
749 virtual void writeEnd(
bool hasPackageInit);
750 virtual bool commit(
const std::vector<std::string>& includes);
767 const std::string& fileSep);
770 virtual void writeEnd(
bool hasPackageInit);
771 virtual bool commit(
const std::vector<std::string>& includes);
784 typedef std::vector<ExportsGenerator*>::iterator
Itr;
797 std::vector<std::string>
commit(
798 const std::vector<std::string>& includes);
801 std::vector<std::string>
remove();
822 bool includePrototype,
824 const std::string& contextId);
835namespace attributes {
840 const std::string& regex)
846 Rcpp::List matches = regmatches(lines, result);
850 template <
typename Stream>
851 void readFile(
const std::string& file, Stream& os) {
852 std::ifstream ifs(file.c_str());
854 throw Rcpp::file_io_error(file);
859 template <
typename Collection>
860 void readLines(std::istream&
is, Collection* pLines) {
863 while(std::getline(
is, line)) {
865 if (line.length() > 0 && *line.rbegin() ==
'\r')
866 line.erase(line.length()-1, 1);
868 pLines->push_back(line);
873 std::vector<FileInfo>* pDependencies) {
877 for (
size_t i = 0; i<pDependencies->size(); ++i) {
878 if (pDependencies->at(i).path() == path)
883 pDependencies->push_back(
FileInfo(path));
887 void parseSourceDependencies(
const std::string& sourceFile,
888 std::vector<FileInfo>* pDependencies) {
904 std::stringstream buffer;
905 readFile(sourceFile, buffer);
910 std::deque<std::string> lines;
911 readLines(buffer, &lines);
916 linesVector,
"^\\s*#include\\s*\"([^\"]+)\"\\s*$");
920 std::vector<FileInfo> newDependencies;
921 for (
int i = 0; i<matches.
size(); i++) {
922 std::string line = lines[i];
930 filepath(sourceDir, std::string(
match[1]));
934 include = normalizePath(include,
"/");
935 if (addUniqueDependency(include, pDependencies)) {
936 newDependencies.push_back(
940 std::vector<std::string> exts;
941 exts.push_back(
".cc");
942 exts.push_back(
".cpp");
943 for (
size_t i = 0; i<exts.size(); ++i) {
947 filePathSansExt(include)) + exts[i];
949 exists = fileExists(file);
951 if (addUniqueDependency(file,
954 newDependencies.push_back(fileInfo);
964 for (
size_t i = 0; i<newDependencies.size(); i++) {
965 FileInfo dependency = newDependencies[i];
966 parseSourceDependencies(dependency.
path(), pDependencies);
971 std::vector<FileInfo> parseSourceDependencies(
972 std::string sourceFile) {
980 std::vector<FileInfo> dependencies;
981 parseSourceDependencies(sourceFile, &dependencies);
984 dependencies.erase(std::remove(dependencies.begin(),
995 std::vector<std::string> parseEmbeddedR(
997 const std::deque<std::string>& lines) {
998 Rcpp::List matches = regexMatches(linesVector,
999 "^\\s*/\\*{3,}\\s*[Rr]\\s*$");
1000 bool withinRBlock =
false;
1002 std::vector<std::string> embeddedR;
1004 for (
int i = 0; i<matches.
size(); i++) {
1007 std::string line = lines[i];
1016 withinRBlock =
true;
1018 else if (withinRBlock) {
1020 embeddedR.push_back(line);
1022 withinRBlock =
false;
1034 std::string Function::signature(
const std::string&
name)
const {
1036 std::ostringstream ostr;
1038 ostr <<
type() <<
"(*" <<
name <<
")(";
1040 const std::vector<Argument>& args =
arguments();
1041 for (std::size_t i = 0; i<args.size(); i++) {
1042 ostr << args[i].type();
1043 if (i != (args.size()-1))
1056 std::string::size_type pos = paramText.find(
"=") ;
1057 if ( pos != std::string::npos ) {
1059 name_ = paramText.substr(0, pos);
1062 value_ = paramText.substr(pos + 1) ;
1075 for (std::vector<Param>::const_iterator
1077 if (it->name() ==
name)
1085 if (!type.
empty()) {
1098 bool printDefault =
true) {
1099 if (!argument.
empty()) {
1100 os << argument.
type();
1101 if (!argument.
name().empty()) {
1103 os << argument.
name();
1119 bool printArgDefaults =
true) {
1128 const std::vector<Argument>& arguments =
function.arguments();
1129 for (std::size_t i = 0; i<arguments.size(); i++) {
1131 if (i != (arguments.size()-1))
1146 if (!param.
empty()) {
1148 if (!param.
value().empty())
1149 os <<
"=" << param.
value();
1156 if (!attribute.
empty()) {
1157 os <<
"[[Rcpp::" << attribute.
name();
1158 const std::vector<Param>& params = attribute.
params();
1159 if (params.size() > 0) {
1161 for (std::size_t i = 0; i<params.size(); i++) {
1163 if (i != (params.size()-1))
1179 const std::string& packageName,
1180 bool parseDependencies)
1185 std::string packageNameCpp = packageName;
1186 std::replace(packageNameCpp.begin(), packageNameCpp.end(),
'.',
'_');
1191 std::stringstream buffer;
1193 std::string contents = buffer.str();
1196 if (contents.find(
"[[Rcpp::") != std::string::npos ||
1197 contents.find(
"RCPP_MODULE") != std::string::npos ||
1198 contents.find(
"R_init_" + packageNameCpp) != std::string::npos) {
1203 std::deque<std::string> lines;
1204 readLines(buffer, &lines);
1210 "^\\s*//\\s*\\[\\[Rcpp::(\\w+)(\\(.*?\\))?\\]\\]\\s*$");
1211 for (
int i = 0; i<matches.
size(); i++) {
1214 std::string line = lines[i];
1221 if (
match.size() > 0) {
1227 if (
match.size() != 3)
1241 if (line.find(
"//'") == 0) {
1242 std::string roxLine =
"#" + line.substr(2);
1255 commentState.
reset();
1257 "^\\s*RCPP_MODULE\\s*\\(\\s*(\\w+)\\s*\\).*$");
1258 for (
int i = 0; i<modMatches.
size(); i++) {
1261 std::string line = lines[i];
1268 if (
match.size() > 0) {
1269 const char * name =
match[1];
1276 commentState.
reset();
1277 std::string pkgInit =
"R_init_" + packageNameCpp;
1278 Rcpp::List initMatches = regexMatches(
lines_,
"^[^/]+" + pkgInit +
".*DllInfo.*$");
1279 for (
int i = 0; i<initMatches.
size(); i++) {
1282 std::string line = lines[i];
1289 if (
match.size() > 0) {
1299 if (parseDependencies) {
1313 it = parser.
begin(); it != parser.
end(); ++it) {
1322 std::copy(parser.
modules().begin(),
1332 const std::vector<std::string>&
match,
1335 std::string name =
match[1];
1344 std::vector<Param> params;
1345 std::string paramsText =
match[2];
1346 if (!paramsText.empty()) {
1353 paramsText = paramsText.substr(1, paramsText.size()-2);
1368 if ((lineNumber + 1) <
lines_.size())
1374 for (std::size_t i=0; i<params.size(); i++) {
1376 std::string name = params[i].name();
1377 std::string value = params[i].value();
1380 if (value.empty() && (i > 0)) {
1386 else if (!value.empty() &&
1419 if (params.empty()) {
1423 for (std::size_t i=0; i<params.size(); i++) {
1424 std::string param = params[i].name();
1427 "Unknown interface '" + param +
"'", lineNumber);
1443 const std::string& input) {
1445 std::string::size_type blockend = input.find_last_of(
kParamBlockEnd);
1447 const std::string delimiters(
",");
1448 std::vector<Param> params;
1449 std::string::size_type current;
1450 std::string::size_type next = std::string::npos;
1451 std::string::size_type signature_param_start = std::string::npos;
1453 next = input.find_first_not_of(delimiters, next + 1);
1454 if (next == std::string::npos)
1458 next = input.find_first_of(delimiters, next + 1);
1459 }
while((next >= blockstart) && (next <= blockend) &&
1460 (next != std::string::npos));
1461 params.push_back(
Param(input.substr(current, next - current)));
1463 signature_param_start = current;
1465 }
while(next != std::string::npos);
1469 if(signature_param_start != std::string::npos) {
1471 signature_param_start < blockstart &&
1472 blockstart < blockend &&
1473 blockstart != std::string::npos &&
1474 blockend != std::string::npos;
1494 std::string::size_type endParenLoc =
signature.find_last_of(
')');
1495 std::string::size_type beginParenLoc =
signature.find_first_of(
'(');
1496 if (endParenLoc == std::string::npos ||
1497 beginParenLoc == std::string::npos ||
1498 endParenLoc < beginParenLoc) {
1508 const std::string preambleText =
signature.substr(0, beginParenLoc);
1509 for (std::string::const_reverse_iterator
1510 it = preambleText.rbegin(); it != preambleText.rend(); ++it) {
1513 if (!name.empty()) {
1516 std::string typeText;
1517 while (++it != preambleText.rend())
1518 typeText.insert(0U, 1U, *it);
1527 name.insert(0U, 1U, ch);
1544 std::vector<Argument> arguments;
1545 std::string argsText =
signature.substr(beginParenLoc + 1,
1546 endParenLoc-beginParenLoc-1);
1548 for (std::vector<std::string>::const_iterator it =
1549 args.begin(); it != args.end(); ++it) {
1552 std::string arg = *it;
1560 std::string defaultValue;
1561 std::string::size_type eqPos = arg.find_first_of(
'=');
1562 if ( (eqPos != std::string::npos) && ((eqPos + 1) < arg.size()) ) {
1563 defaultValue = arg.substr(eqPos+1);
1565 arg = arg.substr(0, eqPos);
1580 if (pos != std::string::npos) {
1582 std::string::size_type ref_pos = arg.substr(pos).find_last_of(
"&");
1583 if (ref_pos != std::string::npos) {
1585 arg.insert(pos,
" ");
1588 name = arg.substr(pos);
1604 arguments.push_back(
Argument(name, type, defaultValue));
1607 return Function(type, name, arguments);
1617 for (
size_t i = lineNumber; i < (size_t)
lines_.size(); i++) {
1620 bool insideQuotes =
false;
1623 for (
size_t c = 0; c < line.length(); ++c) {
1625 char ch = line.at(c);
1627 if (ch ==
'"' && prevChar !=
'\\')
1628 insideQuotes = !insideQuotes;
1630 if (!insideQuotes && ((ch ==
'{') || (ch ==
';'))) {
1645 return std::string();
1653 const std::string& argText) {
1655 int templateCount = 0;
1657 std::string currentArg;
1658 std::vector<std::string> args;
1660 bool escaped =
false;
1661 typedef std::string::const_iterator it_t;
1662 for (it_t it = argText.begin(); it != argText.end(); ++it) {
1668 if ( ! quote && (ch ==
'"' || ch ==
'\''))
1670 else if (quote && ch == quote && ! escaped)
1676 else if (quote && ch ==
'\\')
1682 (templateCount == 0) &&
1683 (parenCount == 0)) {
1684 args.push_back(currentArg);
1690 if ( ! currentArg.empty() || ch !=
' ')
1691 currentArg.push_back(ch);
1712 if (!currentArg.empty())
1713 args.push_back(currentArg);
1720 const std::string constQualifier(
"const");
1721 const std::string referenceQualifier(
"&");
1724 std::string type = text;
1728 bool isConst =
false;
1729 bool isReference =
false;
1730 if (type.find(constQualifier) == 0) {
1732 type.erase(0, constQualifier.length());
1740 if (type.find(referenceQualifier) ==
1741 (type.length() - referenceQualifier.length())) {
1743 type.erase(type.length() - referenceQualifier.length());
1751 return Type(type, isConst, isReference);
1768 const std::string& attribute,
1769 size_t lineNumber) {
1772 Rcpp::Function basename = Rcpp::Environment::base_env()[
"basename"];
1775 std::ostringstream ostr;
1777 if (!attribute.empty())
1778 ostr <<
" for " << attribute <<
" attribute";
1779 ostr <<
" at " << file <<
":" << lineNumber;
1786 size_t lineNumber) {
1792 size_t lineNumber) {
1797 size_t lineNumber) {
1802 const std::string& param,
1803 size_t lineNumber) {
1805 "'" + param +
"'", lineNumber);
1810 size_t lineNumber) {
1812 "Rcpp::interfaces", lineNumber);
1818 std::size_t pos = 0;
1819 while (pos != std::string::npos) {
1822 std::size_t lineCommentPos = line.find(
"//", pos);
1825 std::string token =
inComment() ?
"*/" :
"/*";
1826 pos = line.find(token, pos);
1829 if (pos != std::string::npos) {
1832 if (lineCommentPos != std::string::npos && lineCommentPos < pos)
1836 pos += token.size();
1850namespace attributes {
1854 const char *
const kRcppExportsSuffix =
"_RcppExports.h";
1855 const char *
const kTrySuffix =
"_try";
1860 const std::string& commentPrefix)
1872 std::stringstream buffer;
1873 buffer << ifs.rdbuf();
1908 std::ostringstream headerStream;
1910 <<
"Rcpp::compileAttributes()"
1911 <<
" -> do not edit by hand" << std::endl;
1914 if (!preamble.empty())
1915 headerStream << preamble;
1918 std::string generatedCode = headerStream.str() + code;
1922 std::ofstream::out | std::ofstream::trunc);
1927 ofs << generatedCode;
1943 std::string newname(name);
1944 std::replace(newname.begin(), newname.end(),
'.',
'_');
1950 const std::string& fileSep)
1952 packageDir + fileSep +
"src" + fileSep +
"RcppExports.cpp",
1976 if (it->isExportedFunction()) {
1994 const std::vector<std::string>& modules =
attributes.modules();
2001 for (std::vector<Attribute>::const_iterator
2003 if (it->isExportedFunction())
2004 Rcpp::Rcout <<
" " << it->function() << std::endl;
2018 ostr() << std::endl;
2019 ostr() <<
"// validate"
2020 <<
" (ensure exported C++ functions exist before "
2021 <<
"calling them)" << std::endl;
2023 <<
"(const char* sig) { " << std::endl;
2024 ostr() <<
" static std::set<std::string> signatures;"
2026 ostr() <<
" if (signatures.empty()) {" << std::endl;
2030 ostr() <<
" signatures.insert(\""
2032 <<
"\");" << std::endl;
2034 ostr() <<
" }" << std::endl;
2035 ostr() <<
" return signatures.find(sig) != signatures.end();"
2037 ostr() <<
"}" << std::endl;
2041 ostr() << std::endl;
2042 ostr() <<
"// registerCCallable (register entry points for "
2043 "exported C++ functions)" << std::endl;
2045 <<
"() { " << std::endl;
2052 ostr() << std::endl;
2057 ostr() << std::endl;
2058 ostr() <<
" return R_NilValue;" << std::endl;
2059 ostr() <<
"}" << std::endl;
2066 std::vector<std::string> routineNames;
2067 std::vector<std::size_t> routineArgs;
2073 std::string kRcppModuleBoot =
"_rcpp_module_boot_";
2074 for (std::size_t i=0;i<
modules_.size(); i++) {
2075 routineNames.push_back(kRcppModuleBoot +
modules_[i]);
2076 routineArgs.push_back(0);
2080 routineArgs.push_back(0);
2084 Rcpp::Function extraRoutinesFunc = Environment::namespace_env(
"Rcpp")[
".extraRoutineRegistrations"];
2085 List extraRoutines = extraRoutinesFunc(
targetFile(), routineNames);
2086 std::vector<std::string> declarations = extraRoutines[
"declarations"];
2087 std::vector<std::string>
callEntries = extraRoutines[
"call_entries"];
2090 for (std::size_t i=0;i<
modules_.size(); i++) {
2091 declarations.push_back(
"RcppExport SEXP " + kRcppModuleBoot +
modules_[i] +
"();");
2095 if (declarations.size() > 0) {
2096 ostr() << std::endl;
2097 for (std::size_t i = 0; i<declarations.size(); i++)
2098 ostr() << declarations[i] << std::endl;
2102 ostr() << std::endl;
2103 ostr() <<
"static const R_CallMethodDef CallEntries[] = {" << std::endl;
2104 for (std::size_t i=0;i<routineNames.size(); i++) {
2105 ostr() <<
" {\"" << routineNames[i] <<
"\", " <<
2106 "(DL_FUNC) &" << routineNames[i] <<
", " <<
2107 routineArgs[i] <<
"}," << std::endl;
2110 for (std::size_t i = 0; i<
callEntries.size(); i++)
2113 ostr() <<
" {NULL, NULL, 0}" << std::endl;
2114 ostr() <<
"};" << std::endl;
2116 ostr() << std::endl;
2122 ostr() <<
";" << std::endl;
2125 ostr() <<
"RcppExport void R_init_" <<
packageCpp() <<
"(DllInfo *dll) {" << std::endl;
2126 ostr() <<
" R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);" << std::endl;
2127 ostr() <<
" R_useDynamicSymbols(dll, FALSE);" << std::endl;
2131 ostr() <<
" " <<
function.name() <<
"(dll);" << std::endl;
2133 ostr() <<
"}" << std::endl;
2138 showWarning(
"[[Rcpp::init]] attribute used in a package with an explicit "
2139 "R_init function (Rcpp::init functions will not be called)");
2145 const std::string& exportedName,
2146 const std::string& name)
const {
2147 std::ostringstream
ostr;
2148 std::string indentStr(indent,
' ');
2149 ostr << indentStr <<
"R_RegisterCCallable(\"" <<
package() <<
"\", "
2158 std::ostringstream
ostr;
2159 if (!includes.empty()) {
2160 for (std::size_t i=0;i<includes.size(); i++)
2161 ostr << includes[i] << std::endl;
2164 ostr <<
"#include <string>" << std::endl;
2165 ostr <<
"#include <set>" << std::endl;
2170 ostr <<
"using namespace Rcpp;" << std::endl << std::endl;
2179 const std::string& packageDir,
2181 const std::string& fileSep)
2183 packageDir + fileSep +
"inst" + fileSep +
"include" +
2188 includeDir_ = packageDir + fileSep +
"inst" + fileSep +
"include";
2194 << std::endl << std::endl;
2202 ostr() <<
" using namespace Rcpp;" << std::endl << std::endl;
2207 ostr() <<
" namespace {" << std::endl;
2208 ostr() <<
" void validateSignature(const char* sig) {"
2210 ostr() <<
" Rcpp::Function require = "
2211 <<
"Rcpp::Environment::base_env()[\"require\"];"
2214 <<
"Rcpp::Named(\"quietly\") = true);"
2217 std::string validate =
"validate";
2218 std::string fnType =
"Ptr_" + validate;
2219 ostr() <<
" typedef int(*" << fnType <<
")(const char*);"
2222 std::string ptrName =
"p_" + validate;
2223 ostr() <<
" static " << fnType <<
" " << ptrName <<
" = "
2224 <<
"(" << fnType <<
")" << std::endl
2227 <<
";" << std::endl;
2228 ostr() <<
" if (!" << ptrName <<
"(sig)) {" << std::endl;
2229 ostr() <<
" throw Rcpp::function_not_exported("
2232 <<
"\"C++ function with signature '\" + std::string(sig) + \"' not found in " <<
package()
2233 <<
"\");" << std::endl;
2234 ostr() <<
" }" << std::endl;
2235 ostr() <<
" }" << std::endl;
2237 ostr() <<
" }" << std::endl << std::endl;
2248 for(std::vector<Attribute>::const_iterator
2251 if (it->isExportedFunction()) {
2254 it->function().renamedTo(it->exportedCppName());
2263 std::string fnType =
"Ptr_" +
function.name();
2264 ostr() <<
" typedef SEXP(*" << fnType <<
")(";
2265 for (
size_t i=0; i<
function.arguments().size(); i++) {
2267 if (i != (
function.arguments().size()-1))
2270 ostr() <<
");" << std::endl;
2272 std::string ptrName =
"p_" +
function.name();
2273 ostr() <<
" static " << fnType <<
" "
2274 << ptrName <<
" = NULL;"
2276 ostr() <<
" if (" << ptrName <<
" == NULL) {"
2278 ostr() <<
" validateSignature"
2279 <<
"(\"" <<
function.signature() <<
"\");"
2281 ostr() <<
" " << ptrName <<
" = "
2282 <<
"(" << fnType <<
")"
2285 ostr() <<
" }" << std::endl;
2286 ostr() <<
" RObject rcpp_result_gen;" << std::endl;
2287 ostr() <<
" {" << std::endl;
2289 ostr() <<
" RNGScope RCPP_rngScope_gen;" << std::endl;
2290 ostr() <<
" rcpp_result_gen = " << ptrName <<
"(";
2292 const std::vector<Argument>& args =
function.arguments();
2293 for (std::size_t i = 0; i<args.size(); i++) {
2294 ostr() <<
"Shield<SEXP>(Rcpp::wrap(" << args[i].name() <<
"))";
2295 if (i != (args.size()-1))
2299 ostr() <<
");" << std::endl;
2300 ostr() <<
" }" << std::endl;
2302 ostr() <<
" if (rcpp_result_gen.inherits(\"interrupted-error\"))"
2304 <<
" throw Rcpp::internal::InterruptedException();"
2306 ostr() <<
" if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))"
2308 <<
" throw Rcpp::LongjumpException(rcpp_result_gen);"
2310 ostr() <<
" if (rcpp_result_gen.inherits(\"try-error\"))"
2312 <<
" throw Rcpp::exception(Rcpp::as<std::string>("
2313 <<
"rcpp_result_gen).c_str());"
2316 ostr() <<
" return Rcpp::as<" <<
function.type() <<
" >"
2317 <<
"(rcpp_result_gen);" << std::endl;
2320 ostr() <<
" }" << std::endl << std::endl;
2326 ostr() <<
"}" << std::endl;
2327 ostr() << std::endl;
2332 const std::vector<std::string>& includes) {
2340 std::ostringstream
ostr;
2344 ostr <<
"#ifndef " << guard << std::endl;
2345 ostr <<
"#define " << guard << std::endl << std::endl;
2348 if (!includes.empty()) {
2349 for (std::size_t i=0;i<includes.size(); i++)
2354 std::string preamble =
"#include \"../inst/include/";
2355 std::string pkgInclude = preamble +
packageCpp() +
".h\"";
2356 if (includes[i] == pkgInclude)
2360 std::string typesInclude = preamble +
packageCpp() +
"_types.h";
2361 if (includes[i].
find(typesInclude) != std::string::npos)
2363 std::string include =
"#include \"" +
2364 includes[i].substr(preamble.length());
2365 ostr << include << std::endl;
2369 ostr << includes[i] << std::endl;
2384 const std::string&
function)
const {
2385 std::ostringstream
ostr;
2386 ostr <<
"R_GetCCallable"
2387 <<
"(\"" <<
package() <<
"\", "
2393 return "RCPP_" +
packageCpp() +
"_RCPPEXPORTS_H_GEN_";
2397 const std::string& packageDir,
2399 const std::string& fileSep)
2401 packageDir + fileSep +
"inst" + fileSep +
"include" +
2406 includeDir_ = packageDir + fileSep +
"inst" + fileSep +
"include";
2413 ostr() <<
"#ifndef " << guard << std::endl;
2414 ostr() <<
"#define " << guard << std::endl << std::endl;
2416 <<
"\"" << std::endl;
2418 ostr() << std::endl;
2444 const std::string& fileSep)
2446 packageDir + fileSep +
"R" + fileSep +
"RcppExports.R",
2457 const std::vector<std::vector<std::string> >& roxygenChunks =
2459 for (std::size_t i = 0; i<roxygenChunks.size(); i++) {
2460 const std::vector<std::string>& chunk = roxygenChunks[i];
2461 for (std::size_t l = 0; l < chunk.size(); l++)
2462 ostr() << chunk[l] << std::endl;
2463 ostr() <<
"NULL" << std::endl << std::endl;
2469 for(std::vector<Attribute>::const_iterator
2479 for (
size_t i=0; i<attribute.
roxygen().size(); i++)
2488 std::string rsig_err_msg =
"Missing args in " + args;
2499 ostr() << name <<
" <- function(" << args <<
") {"
2502 if (isInvisibleOrVoid)
2503 ostr() <<
"invisible(";
2511 ostr() <<
"', " <<
"PACKAGE = '" <<
package() <<
"'";
2516 const std::vector<Argument>& arguments =
function.arguments();
2517 for (
size_t i = 0; i<arguments.size(); i++)
2518 ostr() <<
", " << arguments[i].name();
2520 if (isInvisibleOrVoid)
2522 ostr() << std::endl;
2524 ostr() <<
"}" << std::endl << std::endl;
2532 ostr() <<
"# Register entry points for exported C++ functions"
2534 ostr() <<
"methods::setLoadAction(function(ns) {" << std::endl;
2542 << std::endl <<
"})" << std::endl;
2565 (*it)->writeBegin();
2577 (*it)->writeEnd(hasPackageInit);
2582 const std::vector<std::string>& includes) {
2584 std::vector<std::string> updated;
2587 if ((*it)->commit(includes))
2588 updated.push_back((*it)->targetFile());
2596 std::vector<std::string> removed;
2598 if ((*it)->remove())
2599 removed.push_back((*it)->targetFile());
2610 std::string cppNumericArgToRArg(
const std::string& type,
2611 const std::string& cppArg) {
2614 std::stringstream argStream(cppArg);
2615 if ((argStream >> num)) {
2618 if (!argStream.eof()) {
2620 argStream >> suffix;
2621 if (argStream.eof() && suffix ==
"L")
2627 if (cppArg.find(
'.') == std::string::npos &&
2628 type !=
"double" && type !=
"float")
2629 return cppArg +
"L";
2636 return std::string();
2642 std::string cppCreateArgToRArg(
const std::string& cppArg) {
2644 std::string create =
"::create";
2645 size_t createLoc = cppArg.find(create);
2646 if (createLoc == std::string::npos ||
2647 ((createLoc + create.length()) >= cppArg.size())) {
2648 return std::string();
2651 std::string type = cppArg.substr(0, createLoc);
2652 std::string rcppScope =
"Rcpp::";
2653 size_t rcppLoc = type.find(rcppScope);
2654 if (rcppLoc == 0 && type.size() > rcppScope.length())
2655 type = type.substr(rcppScope.length());
2657 std::string args = cppArg.substr(createLoc + create.length());
2658 if (type ==
"CharacterVector")
2659 return "as.character( c" + args +
")";
2660 if (type ==
"IntegerVector")
2661 return "as.integer( c" + args +
")";
2662 if (type ==
"NumericVector")
2663 return "as.numeric( c" + args +
")";
2664 if (type ==
"LogicalVector")
2665 return "as.logical( c" + args +
")";
2667 return std::string();
2672 std::string cppMatrixArgToRArg(
const std::string& cppArg) {
2675 std::string matrix =
"Matrix";
2676 size_t matrixLoc = cppArg.find(matrix);
2677 if (matrixLoc == std::string::npos ||
2678 ((matrixLoc + matrix.length()) >= cppArg.size())) {
2679 return std::string();
2682 std::string args = cppArg.substr(matrixLoc + matrix.length());
2683 return "matrix" + args;
2688 std::string cppLiteralArgToRArg(
const std::string& cppArg) {
2689 if (cppArg ==
"true")
2691 else if (cppArg ==
"false")
2693 else if (cppArg ==
"R_NilValue")
2695 else if (cppArg ==
"NA_STRING")
2696 return "NA_character_";
2697 else if (cppArg ==
"NA_INTEGER")
2698 return "NA_integer_";
2699 else if (cppArg ==
"NA_LOGICAL")
2700 return "NA_integer_";
2701 else if (cppArg ==
"NA_REAL")
2704 return std::string();
2709 std::string cppConstructorArgToRArg(
const std::string& cppArg) {
2712 static std::map<std::string, std::string> RcppContainerToR;
2713 RcppContainerToR.insert(std::make_pair(
"NumericVector",
"numeric"));
2714 RcppContainerToR.insert(std::make_pair(
"DoubleVector",
"numeric"));
2715 RcppContainerToR.insert(std::make_pair(
"CharacterVector",
"character"));
2716 RcppContainerToR.insert(std::make_pair(
"IntegerVector",
"integer"));
2717 RcppContainerToR.insert(std::make_pair(
"LogicalVector",
"logical"));
2718 RcppContainerToR.insert(std::make_pair(
"ComplexVector",
"complex"));
2722 typedef std::map<std::string, std::string>::const_iterator Iterator;
2723 for (Iterator it = RcppContainerToR.begin(); it != RcppContainerToR.end(); ++it) {
2724 size_t loc = cppArg.find(it->first);
2725 if (loc != std::string::npos) {
2726 return it->second + cppArg.substr(it->first.size(), std::string::npos);
2730 return std::string();
2736 std::string cppArgToRArg(
const std::string& type,
2737 const std::string& cppArg) {
2744 std::string rArg = cppLiteralArgToRArg(cppArg);
2749 rArg = cppCreateArgToRArg(cppArg);
2754 rArg = cppMatrixArgToRArg(cppArg);
2759 rArg = cppNumericArgToRArg(type, cppArg);
2764 rArg = cppConstructorArgToRArg(cppArg);
2769 return std::string();
2776 std::ostringstream argsOstr;
2777 const std::vector<Argument>& arguments =
function.arguments();
2778 for (
size_t i = 0; i<arguments.size(); i++) {
2779 const Argument& argument = arguments[i];
2780 argsOstr << argument.
name();
2782 std::string rArg = cppArgToRArg(argument.
type().
name(),
2784 if (!rArg.empty()) {
2785 argsOstr <<
" = " << rArg;
2787 showWarning(
"Unable to parse C++ default value '" +
2789 argument.
name() +
" of function " +
2794 if (i != (arguments.size()-1))
2797 return argsOstr.str();
2802 std::vector<std::string> required_args;
2803 const std::vector<Argument>& arguments =
function.arguments();
2804 for (
size_t i = 0; i<arguments.size(); i++) {
2805 const Argument& argument = arguments[i];
2806 required_args.push_back(argument.
name());
2808 args =
"function(" + args +
") {}";
2812 Rcpp::Environment::namespace_env(
"methods")[
"formalArgs"];
2817 std::vector<std::string> parsed_args =
2820 for(
size_t i=0; i<required_args.size(); ++i) {
2821 if(std::find(parsed_args.begin(), parsed_args.end(),
2822 required_args[i]) == parsed_args.end())
2830 ostr <<
"#ifdef RCPP_USE_GLOBAL_ROSTREAM" << std::endl;
2831 ostr <<
"Rcpp::Rostream<true>& Rcpp::Rcout = Rcpp::Rcpp_cout_get();";
2833 ostr <<
"Rcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();";
2835 ostr <<
"#endif" << std::endl << std::endl;
2842 bool includePrototype,
2844 const std::string& contextId) {
2847 for(std::vector<Attribute>::const_iterator
2857 if (includePrototype) {
2858 ostr <<
"// " <<
function.name() << std::endl;
2866 ostr << (cppInterface ?
"static" :
"RcppExport");
2868 std::string funcName = contextId +
"_" +
function.name();
2873 std::ostringstream ostrArgs;
2874 const std::vector<Argument>& arguments =
function.arguments();
2875 for (
size_t i = 0; i<arguments.size(); i++) {
2876 const Argument& argument = arguments[i];
2877 ostrArgs <<
"SEXP " << argument.
name() <<
"SEXP";
2878 if (i != (arguments.size()-1))
2881 std::string args = ostrArgs.str();
2882 ostr << args <<
") {" << std::endl;
2883 ostr <<
"BEGIN_RCPP" << std::endl;
2885 ostr <<
" Rcpp::RObject rcpp_result_gen;" << std::endl;
2886 if (!cppInterface && attribute.
rng())
2887 ostr <<
" Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
2888 for (
size_t i = 0; i<arguments.size(); i++) {
2889 const Argument& argument = arguments[i];
2891 ostr <<
" Rcpp::traits::input_parameter< "
2893 <<
"(" << argument.
name() <<
"SEXP);" << std::endl;
2898 ostr <<
"rcpp_result_gen = Rcpp::wrap(";
2900 for (
size_t i = 0; i<arguments.size(); i++) {
2901 const Argument& argument = arguments[i];
2902 ostr << argument.
name();
2903 if (i != (arguments.size()-1))
2908 ostr <<
");" << std::endl;
2912 ostr <<
" return rcpp_result_gen;" << std::endl;
2916 ostr <<
" return R_NilValue;" << std::endl;
2918 ostr << (cppInterface ?
"END_RCPP_RETURN_ERROR" :
"END_RCPP")
2920 ostr <<
"}" << std::endl;
2924 ostr <<
"RcppExport SEXP " << funcName <<
"(" << args <<
") {"
2926 ostr <<
" SEXP rcpp_result_gen;" << std::endl;
2927 ostr <<
" {" << std::endl;
2928 if (attribute.
rng())
2929 ostr <<
" Rcpp::RNGScope rcpp_rngScope_gen;" << std::endl;
2930 ostr <<
" rcpp_result_gen = PROTECT(" << funcName
2931 << kTrySuffix <<
"(";
2932 for (
size_t i = 0; i<arguments.size(); i++) {
2933 const Argument& argument = arguments[i];
2934 ostr << argument.
name() <<
"SEXP";
2935 if (i != (arguments.size()-1))
2938 ostr <<
"));" << std::endl;
2939 ostr <<
" }" << std::endl;
2940 ostr <<
" Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, \"interrupted-error\");"
2942 <<
" if (rcpp_isInterrupt_gen) {" << std::endl
2943 <<
" UNPROTECT(1);" << std::endl
2944 <<
" Rf_onintr();" << std::endl
2945 <<
" }" << std::endl
2946 <<
" bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);" << std::endl
2947 <<
" if (rcpp_isLongjump_gen) {" << std::endl
2949 <<
" Rcpp::internal::resumeJump(rcpp_result_gen);" << std::endl
2950 <<
" }" << std::endl
2951 <<
" Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"try-error\");"
2953 <<
" if (rcpp_isError_gen) {" << std::endl
2954 <<
" SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);" << std::endl
2955 <<
" UNPROTECT(1);" << std::endl
2957 <<
" (Rf_error)(\"%s\", CHAR(rcpp_msgSEXP_gen));" << std::endl
2958 <<
" }" << std::endl
2959 <<
" UNPROTECT(1);" << std::endl
2960 <<
" return rcpp_result_gen;" << std::endl
2961 <<
"}" << std::endl;
2982 struct _stat buffer;
2989 if (errno == ENOENT)
3002 Rcpp::Function rm = Rcpp::Environment::base_env()[
"file.remove"];
3014 Rcpp::Function mkdir = Rcpp::Environment::base_env()[
"dir.create"];
3031 if (pStr->empty())
return;
3033 size_t len = pStr->length();
3034 bool inString =
false;
3042 if (idx == std::string::npos)
return;
3045 if (idx + 1 < len && pStr->at(idx) ==
'/' && pStr->at(idx + 1) ==
'/') {
3050 while (idx < len - 1) {
3053 if (pStr->at(idx) ==
'"' && pStr->at(idx - 1) !=
'\\') {
3057 if (pStr->at(idx) ==
'"') {
3063 pStr->at(idx) ==
'/' &&
3064 pStr->at(idx + 1) ==
'/') {
3081 if (pos != std::string::npos)
3082 pStr->erase(pos + 1);
3086 pStr->erase(0, pos);
3091 if (pStr->length() < 2)
3093 char quote = *(pStr->begin());
3094 if ( (quote ==
'\'' || quote ==
'\"') && (*(pStr->rbegin()) == quote) )
3095 *pStr = pStr->substr(1, pStr->length()-2);
3100 if (str.length() < 2)
3102 char quote = *(str.begin());
3103 return (quote ==
'\'' || quote ==
'\"') && (*(str.rbegin()) == quote);
3107 bool endsWith(
const std::string& str,
const std::string& suffix)
3109 return str.size() >= suffix.size() &&
3110 str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
3120 size_t len = str.length();
3121 if (len < 3)
return false;
3123 if (idx == std::string::npos)
return false;
3126 if (len - 2 < idx)
return false;
3128 if (str[idx] ==
'/' &&
3129 str[idx + 1] ==
'/' &&
3130 str[idx + 2] ==
'\'') {
3152 class SourceCppDynlib {
3154 SourceCppDynlib() {}
3156 SourceCppDynlib(
const std::string& cacheDir,
3157 const std::string& cppSourcePath,
3159 : cppSourcePath_(cppSourcePath)
3163 FileInfo cppSourceFilenameInfo(cppSourcePath_);
3164 if (!cppSourceFilenameInfo.exists())
3165 throw Rcpp::file_not_found(cppSourcePath_);
3168 Rcpp::Function basename = Rcpp::Environment::base_env()[
"basename"];
3176 Rcpp::Function tempfile = Rcpp::Environment::base_env()[
"tempfile"];
3178 std::replace(buildDirectory_.begin(), buildDirectory_.end(),
'\\',
'/');
3179 Rcpp::Function dircreate = Rcpp::Environment::base_env()[
"dir.create"];
3180 dircreate(buildDirectory_);
3183 contextId_ =
"sourceCpp_" + uniqueToken(cacheDir);
3186 regenerateSource(cacheDir);
3190 explicit SourceCppDynlib(
const Rcpp::List& dynlib)
3192 using namespace Rcpp;
3194 cppSourcePath_ = as<std::string>(dynlib[
"cppSourcePath"]);
3195 generatedCpp_ = as<std::string>(dynlib[
"generatedCpp"]);
3196 cppSourceFilename_ = as<std::string>(dynlib[
"cppSourceFilename"]);
3197 contextId_ = as<std::string>(dynlib[
"contextId"]);
3198 buildDirectory_ = as<std::string>(dynlib[
"buildDirectory"]);
3199 fileSep_ = as<std::string>(dynlib[
"fileSep"]);
3200 dynlibFilename_ = as<std::string>(dynlib[
"dynlibFilename"]);
3201 previousDynlibFilename_ = as<std::string>(dynlib[
"previousDynlibFilename"]);
3202 dynlibExt_ = as<std::string>(dynlib[
"dynlibExt"]);
3203 exportedFunctions_ = as<std::vector<std::string> >(dynlib[
"exportedFunctions"]);
3204 modules_ = as<std::vector<std::string> >(dynlib[
"modules"]);
3205 depends_ = as<std::vector<std::string> >(dynlib[
"depends"]);
3206 plugins_ = as<std::vector<std::string> >(dynlib[
"plugins"]);
3207 embeddedR_ = as<std::vector<std::string> >(dynlib[
"embeddedR"]);
3208 List sourceDependencies = as<List>(dynlib[
"sourceDependencies"]);
3209 for (R_xlen_t i = 0; i<sourceDependencies.length(); i++) {
3210 List fileInfo = as<List>(sourceDependencies.at(i));
3211 sourceDependencies_.push_back(FileInfo(fileInfo));
3217 using namespace Rcpp;
3219 dynlib[
"cppSourcePath"] = cppSourcePath_;
3220 dynlib[
"generatedCpp"] = generatedCpp_;
3221 dynlib[
"cppSourceFilename"] = cppSourceFilename_;
3222 dynlib[
"contextId"] = contextId_;
3223 dynlib[
"buildDirectory"] = buildDirectory_;
3224 dynlib[
"fileSep"] = fileSep_;
3225 dynlib[
"dynlibFilename"] = dynlibFilename_;
3226 dynlib[
"previousDynlibFilename"] = previousDynlibFilename_;
3227 dynlib[
"dynlibExt"] = dynlibExt_;
3228 dynlib[
"exportedFunctions"] = exportedFunctions_;
3229 dynlib[
"modules"] = modules_;
3230 dynlib[
"depends"] = depends_;
3231 dynlib[
"plugins"] = plugins_;
3232 dynlib[
"embeddedR"] = embeddedR_;
3233 List sourceDependencies;
3234 for (std::size_t i = 0; i<sourceDependencies_.size(); i++) {
3235 FileInfo fileInfo = sourceDependencies_.
at(i);
3238 dynlib[
"sourceDependencies"] = sourceDependencies;
3243 bool isEmpty()
const {
return cppSourcePath_.empty(); }
3245 bool isBuilt()
const {
return FileInfo(dynlibPath()).exists(); };
3247 bool isSourceDirty()
const {
3249 if (FileInfo(cppSourcePath_).lastModified() >
3250 FileInfo(generatedCppSourcePath()).lastModified())
3254 if (!FileInfo(dynlibPath()).
exists())
3258 std::vector<FileInfo> sourceDependencies = parseSourceDependencies(
3260 if (sourceDependencies != sourceDependencies_)
3267 void regenerateSource(
const std::string& cacheDir) {
3270 previousDynlibFilename_ = dynlibFilename_;
3271 dynlibFilename_ =
"sourceCpp_" + uniqueToken(cacheDir) + dynlibExt_;
3274 Rcpp::Function filecopy = Rcpp::Environment::base_env()[
"file.copy"];
3275 filecopy(cppSourcePath_, generatedCppSourcePath(),
true,
Rcpp::_[
"copy.mode"] =
false);
3278 SourceFileAttributesParser sourceAttributes(cppSourcePath_,
"",
true);
3281 std::ostringstream ostr;
3283 ostr << std::endl << std::endl;
3284 ostr <<
"#include <Rcpp.h>" << std::endl;
3287 generateCpp(ostr, sourceAttributes,
true,
false, contextId_);
3288 generatedCpp_ = ostr.str();
3289 std::ofstream cppOfs(generatedCppSourcePath().c_str(),
3290 std::ofstream::out | std::ofstream::app);
3292 throw Rcpp::file_io_error(generatedCppSourcePath());
3293 cppOfs << generatedCpp_;
3297 std::ofstream rOfs(generatedRSourcePath().c_str(),
3298 std::ofstream::out | std::ofstream::trunc);
3300 throw Rcpp::file_io_error(generatedRSourcePath());
3303 std::string dllInfo =
"`." + contextId_ +
"_DLLInfo`";
3304 rOfs << dllInfo <<
" <- dyn.load('" << dynlibPath() <<
"')"
3305 << std::endl << std::endl;
3308 generateR(rOfs, sourceAttributes, dllInfo);
3311 rOfs << std::endl <<
"rm(" << dllInfo <<
")"
3317 exportedFunctions_.clear();
3320 for (SourceFileAttributesParser::const_iterator
3321 it = sourceAttributes.begin(); it != sourceAttributes.end(); ++it) {
3324 exportedFunctions_.push_back(it->exportedName());
3327 for (
size_t i = 0; i<it->params().size(); ++i)
3328 depends_.push_back(it->params()[i].name());
3332 for (
size_t i = 0; i<it->params().size(); ++i)
3333 plugins_.push_back(it->params()[i].name());
3338 modules_ = sourceAttributes.modules();
3341 embeddedR_ = sourceAttributes.embeddedR();
3344 sourceDependencies_ = sourceAttributes.sourceDependencies();
3347 const std::string& contextId()
const {
3351 const std::string& cppSourcePath()
const {
3352 return cppSourcePath_;
3355 const std::vector<std::string> cppDependencySourcePaths() {
3356 std::vector<std::string> dependencies;
3357 for (
size_t i = 0; i<sourceDependencies_.size(); ++i) {
3358 FileInfo dep = sourceDependencies_[i];
3360 dependencies.push_back(dep.
path());
3363 return dependencies;
3366 std::string buildDirectory()
const {
3367 return buildDirectory_;
3370 std::string generatedCpp()
const {
3371 return generatedCpp_;
3374 std::string cppSourceFilename()
const {
3375 return cppSourceFilename_;
3378 std::string rSourceFilename()
const {
3379 return cppSourceFilename() +
".R";
3382 std::string dynlibFilename()
const {
3383 return dynlibFilename_;
3386 std::string dynlibPath()
const {
3387 return buildDirectory_ + fileSep_ + dynlibFilename();
3390 std::string previousDynlibPath()
const {
3391 if (!previousDynlibFilename_.empty())
3392 return buildDirectory_ + fileSep_ + previousDynlibFilename_;
3394 return std::string();
3397 const std::vector<std::string>& exportedFunctions()
const {
3398 return exportedFunctions_;
3401 const std::vector<std::string>& modules()
const {
3405 const std::vector<std::string>& depends()
const {
return depends_; };
3407 const std::vector<std::string>& plugins()
const {
return plugins_; };
3409 const std::vector<std::string>& embeddedR()
const {
return embeddedR_; }
3413 std::string generatedCppSourcePath()
const {
3414 return buildDirectory_ + fileSep_ + cppSourceFilename();
3417 std::string generatedRSourcePath()
const {
3418 return buildDirectory_ + fileSep_ + rSourceFilename();
3421 void generateR(std::ostream& ostr,
3422 const SourceFileAttributes& attributes,
3423 const std::string& dllInfo)
const
3426 for(std::vector<Attribute>::const_iterator
3427 it = attributes.
begin(); it != attributes.
end(); ++it) {
3430 const Attribute& attribute = *it;
3442 std::string rsig_err_msg =
"Missing args in " + args;
3443 throw Rcpp::exception(rsig_err_msg.c_str());
3449 <<
" <- Rcpp:::sourceCppFunction("
3450 <<
"function(" << args <<
") {}, "
3451 << (
function.type().isVoid() ?
"TRUE" :
"FALSE") <<
", "
3453 <<
"'" << contextId_ +
"_" +
function.name()
3454 <<
"')" << std::endl;
3458 std::vector<std::string> modules = attributes.
modules();
3459 if (modules.size() > 0)
3462 ostr <<
"library(Rcpp)" << std::endl;
3465 for (std::vector<std::string>::const_iterator
3466 it = modules.begin(); it != modules.end(); ++it)
3468 ostr <<
" populate( Rcpp::Module(\"" << *it <<
"\","
3469 << dllInfo <<
"), environment() ) " << std::endl;
3475 std::string uniqueToken(
const std::string& cacheDir) {
3477 Rcpp::Function uniqueTokenFunc = rcppEnv[
".sourceCppDynlibUniqueToken"];
3482 std::string cppSourcePath_;
3483 std::string generatedCpp_;
3484 std::string cppSourceFilename_;
3485 std::string contextId_;
3486 std::string buildDirectory_;
3487 std::string fileSep_;
3488 std::string dynlibFilename_;
3489 std::string previousDynlibFilename_;
3490 std::string dynlibExt_;
3491 std::vector<std::string> exportedFunctions_;
3492 std::vector<std::string> modules_;
3493 std::vector<std::string> depends_;
3494 std::vector<std::string> plugins_;
3495 std::vector<std::string> embeddedR_;
3496 std::vector<FileInfo> sourceDependencies_;
3501 void dynlibCacheInsert(
const std::string& cacheDir,
3502 const std::string& file,
3503 const std::string& code,
3504 const SourceCppDynlib& dynlib)
3507 Rcpp::Function dynlibInsertFunc = rcppEnv[
".sourceCppDynlibInsert"];
3508 dynlibInsertFunc(cacheDir, file, code, dynlib.toList());
3511 void dynlibCacheInsertFile(
const std::string& cacheDir,
3512 const std::string& file,
3513 const SourceCppDynlib& dynlib)
3515 dynlibCacheInsert(cacheDir, file,
"", dynlib);
3518 void dynlibCacheInsertCode(
const std::string& cacheDir,
3519 const std::string& code,
3520 const SourceCppDynlib& dynlib)
3522 dynlibCacheInsert(cacheDir,
"", code, dynlib);
3525 SourceCppDynlib dynlibCacheLookup(
const std::string& cacheDir,
3526 const std::string& file,
3527 const std::string& code)
3530 Rcpp::Function dynlibLookupFunc = rcppEnv[
".sourceCppDynlibLookup"];
3531 Rcpp::List dynlibList = dynlibLookupFunc(cacheDir, file, code);
3532 if (dynlibList.
length() > 0)
3533 return SourceCppDynlib(dynlibList);
3535 return SourceCppDynlib();
3538 SourceCppDynlib dynlibCacheLookupByFile(
const std::string& cacheDir,
3539 const std::string& file)
3541 return dynlibCacheLookup(cacheDir, file,
"");
3544 SourceCppDynlib dynlibCacheLookupByCode(
const std::string& cacheDir,
3545 const std::string& code)
3547 return dynlibCacheLookup(cacheDir,
"", code);
3555 SEXP sRebuild, SEXP sCacheDir, SEXP sPlatform) {
3565 SourceCppDynlib dynlib = !code.empty() ? dynlibCacheLookupByCode(cacheDir, code)
3566 : dynlibCacheLookupByFile(cacheDir, file);
3569 bool buildRequired =
false;
3572 if (dynlib.isEmpty()) {
3573 buildRequired =
true;
3574 dynlib = SourceCppDynlib(cacheDir, file, platform);
3578 else if (rebuild || dynlib.isSourceDirty()) {
3579 buildRequired =
true;
3580 dynlib.regenerateSource(cacheDir);
3584 else if (!dynlib.isBuilt()) {
3585 buildRequired =
true;
3590 dynlibCacheInsertCode(cacheDir, code, dynlib);
3592 dynlibCacheInsertFile(cacheDir, file, dynlib);
3595 using namespace Rcpp;
3597 _[
"contextId"] = dynlib.contextId(),
3598 _[
"cppSourcePath"] = dynlib.cppSourcePath(),
3599 _[
"cppDependencySourcePaths"] = dynlib.cppDependencySourcePaths(),
3600 _[
"buildRequired"] = buildRequired,
3601 _[
"buildDirectory"] = dynlib.buildDirectory(),
3602 _[
"generatedCpp"] = dynlib.generatedCpp(),
3603 _[
"exportedFunctions"] = dynlib.exportedFunctions(),
3604 _[
"modules"] = dynlib.modules(),
3605 _[
"cppSourceFilename"] = dynlib.cppSourceFilename(),
3606 _[
"rSourceFilename"] = dynlib.rSourceFilename(),
3607 _[
"dynlibFilename"] = dynlib.dynlibFilename(),
3608 _[
"dynlibPath"] = dynlib.dynlibPath(),
3609 _[
"previousDynlibPath"] = dynlib.previousDynlibPath(),
3610 _[
"depends"] = dynlib.depends(),
3611 _[
"plugins"] = dynlib.plugins(),
3612 _[
"embeddedR"] = dynlib.embeddedR());
3623 SEXP sCppFileBasenames,
3633 std::set<std::string> depends;
3635 it = vDepends.
begin(); it != vDepends.
end(); ++it) {
3636 depends.insert(std::string(*it));
3641 std::vector<std::string> cppFiles =
3643 std::vector<std::string> cppFileBasenames =
3645 std::vector<std::string> includes =
3665 "The header file '" + e.
filePath() +
"' already exists so "
3666 "cannot be overwritten by Rcpp::interfaces";
3683 bool hasPackageInit =
false;
3684 bool haveAttributes =
false;
3685 std::set<std::string> dependsAttribs;
3686 for (std::size_t i=0; i<cppFiles.size(); i++) {
3689 std::string cppFile = cppFiles[i];
3690 if (
endsWith(cppFile,
"RcppExports.cpp"))
3697 if (!hasPackageInit &&
attributes.hasPackageInit())
3698 hasPackageInit =
true;
3705 haveAttributes =
true;
3714 for (
size_t i = 0; i<it->params().size(); ++i)
3715 dependsAttribs.insert(it->params()[i].name());
3721 generators.
writeEnd(hasPackageInit);
3724 std::vector<std::string> updated;
3726 updated = generators.
commit(includes);
3728 updated = generators.
remove();
3732 std::vector<std::string>
diff;
3733 std::set_difference(dependsAttribs.begin(), dependsAttribs.end(),
3734 depends.begin(), depends.end(),
3735 std::back_inserter(
diff));
3736 if (!
diff.empty()) {
3738 "The following packages are referenced using Rcpp::depends "
3739 "attributes however are not listed in the Depends, Imports or "
3740 "LinkingTo fields of the package DESCRIPTION file: ";
3741 for (
size_t i=0; i<
diff.size(); i++) {
3743 if (i != (
diff.size()-1))
3751 for (
size_t i=0; i<updated.size(); i++)
3752 Rcpp::Rcout << updated[i] <<
" updated." << std::endl;
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)
void push_back(const T &object)
Proxy at(const size_t &i)
traits::r_vector_iterator< RTYPE, PreserveStorage >::type iterator
const std::string & defaultValue() const
Argument(const std::string &name, const Type &type, const std::string &defaultValue)
const std::string & name() const
bool operator!=(const Argument &other) const
const Type & type() const
std::string defaultValue_
bool operator==(const Argument &other) 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::vector< Param > & params() 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::string & name() 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
virtual bool commit(const std::vector< std::string > &includes)=0
std::string registerCCallableExportedName()
const std::string & packageCpp() const
std::string exportValidationFunctionRegisteredName()
std::string existingCode_
const std::string packageCppPrefix() const
std::string commentPrefix_
virtual void writeEnd(bool hasPackageInit)=0
const std::string & package() const
ExportsGenerator & operator=(const ExportsGenerator &)
std::string dotNameHelper(const std::string &name) const
virtual ~ExportsGenerator()
const std::string & targetFile() const
bool isSafeToOverwrite() const
std::ostringstream codeStream_
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()
ExportsGenerators & operator=(const ExportsGenerators &)
virtual ~ExportsGenerators()
void writeFunctions(const SourceFileAttributes &attributes, bool verbose)
std::vector< ExportsGenerator * > generators_
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
std::ostream & operator<<(std::ostream &os) const
FileInfo(const List &fileInfo)
double lastModified() 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 & name() const
bool operator!=(const Param &other) const
bool operator==(const Param &other) const
const std::string & value() 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::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)
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
void rcppExportNoFunctionFoundWarning(size_t lineNumber)
virtual const std::string & sourceFile() const
virtual const std::vector< std::string > & modules() const
virtual const_iterator begin() const
std::vector< std::string > roxygenBuffer_
Function parseFunction(size_t lineNumber)
SourceFileAttributesParser & operator=(const SourceFileAttributesParser &)
std::vector< std::string > modules_
Type parseType(const std::string &text)
virtual const_iterator end() const
std::vector< std::string > embeddedR_
virtual bool hasGeneratorOutput() const
const std::vector< FileInfo > & sourceDependencies() const
virtual const std::vector< std::vector< std::string > > & roxygenChunks() const
SourceFileAttributesParser(const SourceFileAttributesParser &)
std::vector< FileInfo > sourceDependencies_
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)
std::vector< Param > parseParameters(const std::string &input)
const std::vector< std::string > & embeddedR() const
std::vector< std::string > parseArguments(const std::string &argText)
virtual const std::vector< std::vector< std::string > > & roxygenChunks() const =0
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 std::vector< std::string > & modules() const =0
virtual const_iterator begin() const =0
virtual ~SourceFileAttributes()
virtual bool hasInterface(const std::string &name) const =0
const std::string & name() const
bool operator!=(const Type &other) const
Type(const std::string &name, bool isConst, bool isReference)
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
sugar::Diff< INTSXP, LHS_NA, LHS_T > diff(const VectorBase< INTSXP, LHS_NA, LHS_T > &lhs)
Argument Named(const std::string &name)
Vector< STRSXP > CharacterVector
Vector< LGLSXP > LogicalVector
SEXP find(const std::string &name) const
RObject_Impl< PreserveStorage > RObject
static internal::NamedPlaceHolder _
static Rostream< true > Rcout
IntegerVector match(const VectorBase< RTYPE, NA, T > &x, const VectorBase< RTYPE, RHS_NA, RHS_T > &table_)
void function(const char *name_, RESULT_TYPE(*fun)(T... t), const char *docstring=0)
Environment_Impl< PreserveStorage > Environment
bool exists(const std::string &name) const
void signature(std::string &s, const char *name)
void warning(const std::string &message)
SEXP wrap(const Date &date)
static R_CallMethodDef callEntries[]