[Rcpp-commits] r3906 - pkg/Rcpp/src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Nov 7 02:29:23 CET 2012
Author: jjallaire
Date: 2012-11-07 02:29:23 +0100 (Wed, 07 Nov 2012)
New Revision: 3906
Modified:
pkg/Rcpp/src/Attributes.cpp
pkg/Rcpp/src/AttributesParser.h
Log:
re-order functions and prune includes
Modified: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp 2012-11-07 00:50:04 UTC (rev 3905)
+++ pkg/Rcpp/src/Attributes.cpp 2012-11-07 01:29:23 UTC (rev 3906)
@@ -29,13 +29,15 @@
#include <sys/stat.h>
#include <errno.h>
-#include <Rcpp.h>
+#include <Rcpp/Function.h>
+#include <Rcpp/Environment.h>
#include <Rcpp/exceptions.h>
#include "AttributesParser.h"
using namespace Rcpp::attributes_parser;
+// General utilities
namespace {
// Utility class for getting file existence and last modified time
@@ -130,17 +132,12 @@
}
}
}
+} // anonymous namespace
+
+
+// Implementation helpers for compileAttributes
+namespace {
- // Generate a module declaration
- void generateCppModule(std::ostream& ostr,
- const std::string& moduleName,
- const SourceFileAttributes& attributes,
- bool verbose) {
- ostr << "RCPP_MODULE(" << moduleName << ") {" << std::endl;
- generateCppModuleFunctions(ostr, attributes, verbose);
- ostr << "}" << std::endl;
- }
-
// Generate placeholder function declaration (for roxygen)
void generateRoxygenPlaceholder(std::ostream& ostr,
const Attribute& attribute) {
@@ -172,214 +169,6 @@
}
}
- // Class that manages generation of source code for the sourceCpp dynlib
- class SourceCppDynlib {
- public:
- SourceCppDynlib() {}
-
- SourceCppDynlib(const std::string& cppSourcePath, Rcpp::List platform)
- : cppSourcePath_(cppSourcePath)
-
- {
- // get cpp source file info
- FileInfo cppSourceFilenameInfo(cppSourcePath_);
- if (!cppSourceFilenameInfo.exists())
- throw Rcpp::file_not_found(cppSourcePath_);
-
- // get last modified time
- cppSourceLastModified_ = cppSourceFilenameInfo.lastModified();
-
- // record the base name of the source file
- Rcpp::Function basename = Rcpp::Environment::base_env()["basename"];
- cppSourceFilename_ = Rcpp::as<std::string>(basename(cppSourcePath_));
-
- // get platform info
- fileSep_ = Rcpp::as<std::string>(platform["file.sep"]);
- dynlibExt_ = Rcpp::as<std::string>(platform["dynlib.ext"]);
-
- // generate temp directory
- Rcpp::Function tempfile = Rcpp::Environment::base_env()["tempfile"];
- buildDirectory_ = Rcpp::as<std::string>(tempfile("sourcecpp_"));
- std::replace(buildDirectory_.begin(), buildDirectory_.end(), '\\', '/');
- Rcpp::Function dircreate = Rcpp::Environment::base_env()["dir.create"];
- dircreate(buildDirectory_);
-
- // generate a random module name
- Rcpp::Function sample = Rcpp::Environment::base_env()["sample"];
- std::ostringstream ostr;
- ostr << "sourceCpp_" << Rcpp::as<int>(sample(100000, 1));
- moduleName_ = ostr.str();
-
- // regenerate the source code
- regenerateSource();
- }
-
- bool isEmpty() const { return cppSourcePath_.empty(); }
-
- bool isBuilt() const { return FileInfo(dynlibPath()).exists(); };
-
- bool isSourceDirty() const {
- // source file out of date means we're dirty
- if (FileInfo(cppSourcePath_).lastModified() >
- FileInfo(generatedCppSourcePath()).lastModified())
- return true;
-
- // no dynlib means we're dirty
- if (!FileInfo(dynlibPath()).exists())
- return true;
-
- // not dirty
- return false;
- }
-
- void regenerateSource() {
-
- // copy the source file to the build dir
- Rcpp::Function filecopy = Rcpp::Environment::base_env()["file.copy"];
- filecopy(cppSourcePath_, generatedCppSourcePath(), true);
-
- // parse attributes
- SourceFileAttributes sourceAttributes(cppSourcePath_);
-
- // generate RCPP module
- std::ostringstream ostr;
- generateCppModule(ostr, moduleName(), sourceAttributes, false);
- generatedCpp_ = ostr.str();
-
- // open source file and append module
- std::ofstream cppOfs(generatedCppSourcePath().c_str(),
- std::ofstream::out | std::ofstream::app);
- if (cppOfs.fail())
- throw Rcpp::file_io_error(generatedCppSourcePath());
- cppOfs << std::endl;
- cppOfs << generatedCpp_;
- cppOfs.close();
-
- // discover exported functions, and dependencies
- exportedFunctions_.clear();
- depends_.clear();
- for (SourceFileAttributes::const_iterator
- it = sourceAttributes.begin(); it != sourceAttributes.end(); ++it) {
- if (it->name() == kExportAttribute && !it->function().empty())
- exportedFunctions_.push_back(exportedName(*it));
-
- else if (it->name() == kDependsAttribute) {
- for (size_t i = 0; i<it->params().size(); ++i)
- depends_.push_back(it->params()[i].name());
- }
- }
- }
-
- const std::string& moduleName() const {
- return moduleName_;
- }
-
- const std::string& cppSourcePath() const {
- return cppSourcePath_;
- }
-
- std::string buildDirectory() const {
- return buildDirectory_;
- }
-
- std::string generatedCpp() const {
- return generatedCpp_;
- }
-
- std::string cppSourceFilename() const {
- return cppSourceFilename_;
- }
-
- std::string dynlibFilename() const {
- return moduleName() + dynlibExt_;
- }
-
- std::string dynlibPath() const {
- return buildDirectory_ + fileSep_ + dynlibFilename();
- }
-
- const std::vector<std::string>& exportedFunctions() const {
- return exportedFunctions_;
- }
-
- const std::vector<std::string>& depends() const { return depends_; };
-
- private:
-
- std::string generatedCppSourcePath() const {
- return buildDirectory_ + fileSep_ + cppSourceFilename();
- }
-
- private:
- std::string cppSourcePath_;
- time_t cppSourceLastModified_;
- std::string generatedCpp_;
- std::string cppSourceFilename_;
- std::string moduleName_;
- std::string buildDirectory_;
- std::string fileSep_;
- std::string dynlibExt_;
- std::vector<std::string> exportedFunctions_;
- std::vector<std::string> depends_;
- };
-
- // Dynlib cache that allows lookup by either file path or code contents
- class SourceCppDynlibCache {
-
- public:
- SourceCppDynlibCache() {}
-
- private:
- // prohibit copying
- SourceCppDynlibCache(const SourceCppDynlibCache&);
- SourceCppDynlibCache& operator=(const SourceCppDynlibCache&);
-
- public:
- // Insert into cache by file name
- void insertFile(const std::string& file, const SourceCppDynlib& dynlib) {
- Entry entry;
- entry.file = file;
- entry.dynlib = dynlib;
- entries_.push_back(entry);
- }
-
- // Insert into cache by code
- void insertCode(const std::string& code, const SourceCppDynlib& dynlib) {
- Entry entry;
- entry.code = code;
- entry.dynlib = dynlib;
- entries_.push_back(entry);
- }
-
- // Lookup by file
- SourceCppDynlib lookupByFile(const std::string& file) {
- for (std::size_t i = 0; i < entries_.size(); i++) {
- if (entries_[i].file == file)
- return entries_[i].dynlib;
- }
-
- return SourceCppDynlib();
- }
-
- // Lookup by code
- SourceCppDynlib lookupByCode(const std::string& code) {
- for (std::size_t i = 0; i < entries_.size(); i++) {
- if (entries_[i].code == code)
- return entries_[i].dynlib;
- }
-
- return SourceCppDynlib();
- }
-
- private:
- struct Entry {
- std::string file;
- std::string code;
- SourceCppDynlib dynlib;
- };
- std::vector<Entry> entries_;
- };
-
// Abstract class which manages writing of code for compileAttributes
class ExportsGenerator {
protected:
@@ -513,7 +302,6 @@
std::ostringstream codeStream_;
};
-
// Class which manages generating RcppExports.cpp
class CppExportsGenerator : public ExportsGenerator {
public:
@@ -825,63 +613,6 @@
} // anonymous namespace
-// Create temporary build directory, generate code as necessary, and return
-// the context required for the sourceCpp function to complete it's work
-RcppExport SEXP sourceCppContext(SEXP sFile, SEXP sCode, SEXP sPlatform) {
-BEGIN_RCPP
- // parameters
- std::string file = Rcpp::as<std::string>(sFile);
- std::string code = sCode != R_NilValue ? Rcpp::as<std::string>(sCode) : "";
- Rcpp::List platform = Rcpp::as<Rcpp::List>(sPlatform);
-
- // get dynlib (using cache if possible)
- static SourceCppDynlibCache s_dynlibCache;
- SourceCppDynlib dynlib;
- if (!code.empty())
- dynlib = s_dynlibCache.lookupByCode(code);
- else
- dynlib = s_dynlibCache.lookupByFile(file);
-
- // check dynlib build state
- bool buildRequired = false;
-
- // if there is no dynlib in the cache then create one
- if (dynlib.isEmpty()) {
- buildRequired = true;
- dynlib = SourceCppDynlib(file, platform);
- if (!code.empty())
- s_dynlibCache.insertCode(code, dynlib);
- else
- s_dynlibCache.insertFile(file, dynlib);
- }
-
- // if the cached dynlib is dirty then regenerate the source
- else if (dynlib.isSourceDirty()) {
- buildRequired = true;
- dynlib.regenerateSource();
- }
-
- // if the dynlib hasn't yet been built then note that
- else if (!dynlib.isBuilt()) {
- buildRequired = true;
- }
-
- // return context as a list
- Rcpp::List context;
- context["moduleName"] = dynlib.moduleName();
- context["cppSourcePath"] = dynlib.cppSourcePath();
- context["buildRequired"] = buildRequired;
- context["buildDirectory"] = dynlib.buildDirectory();
- context["generatedCpp"] = dynlib.generatedCpp();
- context["exportedFunctions"] = dynlib.exportedFunctions();
- context["cppSourceFilename"] = dynlib.cppSourceFilename();
- context["dynlibFilename"] = dynlib.dynlibFilename();
- context["dynlibPath"] = dynlib.dynlibPath();
- context["depends"] = dynlib.depends();
- return Rcpp::wrap(context);
-END_RCPP
-}
-
// Compile the attributes within the specified package directory into
// RcppExports.cpp and RcppExports.R
RcppExport SEXP compileAttributes(SEXP sPackageDir,
@@ -957,3 +688,276 @@
return Rcpp::wrap<std::vector<std::string> >(updated);
END_RCPP
}
+
+
+// Implementation helpers for sourceCppContext
+namespace {
+
+ // Class that manages generation of source code for the sourceCpp dynlib
+ class SourceCppDynlib {
+ public:
+ SourceCppDynlib() {}
+
+ SourceCppDynlib(const std::string& cppSourcePath, Rcpp::List platform)
+ : cppSourcePath_(cppSourcePath)
+
+ {
+ // get cpp source file info
+ FileInfo cppSourceFilenameInfo(cppSourcePath_);
+ if (!cppSourceFilenameInfo.exists())
+ throw Rcpp::file_not_found(cppSourcePath_);
+
+ // get last modified time
+ cppSourceLastModified_ = cppSourceFilenameInfo.lastModified();
+
+ // record the base name of the source file
+ Rcpp::Function basename = Rcpp::Environment::base_env()["basename"];
+ cppSourceFilename_ = Rcpp::as<std::string>(basename(cppSourcePath_));
+
+ // get platform info
+ fileSep_ = Rcpp::as<std::string>(platform["file.sep"]);
+ dynlibExt_ = Rcpp::as<std::string>(platform["dynlib.ext"]);
+
+ // generate temp directory
+ Rcpp::Function tempfile = Rcpp::Environment::base_env()["tempfile"];
+ buildDirectory_ = Rcpp::as<std::string>(tempfile("sourcecpp_"));
+ std::replace(buildDirectory_.begin(), buildDirectory_.end(), '\\', '/');
+ Rcpp::Function dircreate = Rcpp::Environment::base_env()["dir.create"];
+ dircreate(buildDirectory_);
+
+ // generate a random module name
+ Rcpp::Function sample = Rcpp::Environment::base_env()["sample"];
+ std::ostringstream ostr;
+ ostr << "sourceCpp_" << Rcpp::as<int>(sample(100000, 1));
+ moduleName_ = ostr.str();
+
+ // regenerate the source code
+ regenerateSource();
+ }
+
+ bool isEmpty() const { return cppSourcePath_.empty(); }
+
+ bool isBuilt() const { return FileInfo(dynlibPath()).exists(); };
+
+ bool isSourceDirty() const {
+ // source file out of date means we're dirty
+ if (FileInfo(cppSourcePath_).lastModified() >
+ FileInfo(generatedCppSourcePath()).lastModified())
+ return true;
+
+ // no dynlib means we're dirty
+ if (!FileInfo(dynlibPath()).exists())
+ return true;
+
+ // not dirty
+ return false;
+ }
+
+ void regenerateSource() {
+
+ // copy the source file to the build dir
+ Rcpp::Function filecopy = Rcpp::Environment::base_env()["file.copy"];
+ filecopy(cppSourcePath_, generatedCppSourcePath(), true);
+
+ // parse attributes
+ SourceFileAttributes sourceAttributes(cppSourcePath_);
+
+ // generate RCPP module
+ std::ostringstream ostr;
+ ostr << "RCPP_MODULE(" << moduleName() << ") {" << std::endl;
+ generateCppModuleFunctions(ostr, sourceAttributes, false);
+ ostr << "}" << std::endl;
+ generatedCpp_ = ostr.str();
+
+ // open source file and append module
+ std::ofstream cppOfs(generatedCppSourcePath().c_str(),
+ std::ofstream::out | std::ofstream::app);
+ if (cppOfs.fail())
+ throw Rcpp::file_io_error(generatedCppSourcePath());
+ cppOfs << std::endl;
+ cppOfs << generatedCpp_;
+ cppOfs.close();
+
+ // discover exported functions, and dependencies
+ exportedFunctions_.clear();
+ depends_.clear();
+ for (SourceFileAttributes::const_iterator
+ it = sourceAttributes.begin(); it != sourceAttributes.end(); ++it) {
+ if (it->name() == kExportAttribute && !it->function().empty())
+ exportedFunctions_.push_back(exportedName(*it));
+
+ else if (it->name() == kDependsAttribute) {
+ for (size_t i = 0; i<it->params().size(); ++i)
+ depends_.push_back(it->params()[i].name());
+ }
+ }
+ }
+
+ const std::string& moduleName() const {
+ return moduleName_;
+ }
+
+ const std::string& cppSourcePath() const {
+ return cppSourcePath_;
+ }
+
+ std::string buildDirectory() const {
+ return buildDirectory_;
+ }
+
+ std::string generatedCpp() const {
+ return generatedCpp_;
+ }
+
+ std::string cppSourceFilename() const {
+ return cppSourceFilename_;
+ }
+
+ std::string dynlibFilename() const {
+ return moduleName() + dynlibExt_;
+ }
+
+ std::string dynlibPath() const {
+ return buildDirectory_ + fileSep_ + dynlibFilename();
+ }
+
+ const std::vector<std::string>& exportedFunctions() const {
+ return exportedFunctions_;
+ }
+
+ const std::vector<std::string>& depends() const { return depends_; };
+
+ private:
+
+ std::string generatedCppSourcePath() const {
+ return buildDirectory_ + fileSep_ + cppSourceFilename();
+ }
+
+ private:
+ std::string cppSourcePath_;
+ time_t cppSourceLastModified_;
+ std::string generatedCpp_;
+ std::string cppSourceFilename_;
+ std::string moduleName_;
+ std::string buildDirectory_;
+ std::string fileSep_;
+ std::string dynlibExt_;
+ std::vector<std::string> exportedFunctions_;
+ std::vector<std::string> depends_;
+ };
+
+ // Dynlib cache that allows lookup by either file path or code contents
+ class SourceCppDynlibCache {
+
+ public:
+ SourceCppDynlibCache() {}
+
+ private:
+ // prohibit copying
+ SourceCppDynlibCache(const SourceCppDynlibCache&);
+ SourceCppDynlibCache& operator=(const SourceCppDynlibCache&);
+
+ public:
+ // Insert into cache by file name
+ void insertFile(const std::string& file, const SourceCppDynlib& dynlib) {
+ Entry entry;
+ entry.file = file;
+ entry.dynlib = dynlib;
+ entries_.push_back(entry);
+ }
+
+ // Insert into cache by code
+ void insertCode(const std::string& code, const SourceCppDynlib& dynlib) {
+ Entry entry;
+ entry.code = code;
+ entry.dynlib = dynlib;
+ entries_.push_back(entry);
+ }
+
+ // Lookup by file
+ SourceCppDynlib lookupByFile(const std::string& file) {
+ for (std::size_t i = 0; i < entries_.size(); i++) {
+ if (entries_[i].file == file)
+ return entries_[i].dynlib;
+ }
+
+ return SourceCppDynlib();
+ }
+
+ // Lookup by code
+ SourceCppDynlib lookupByCode(const std::string& code) {
+ for (std::size_t i = 0; i < entries_.size(); i++) {
+ if (entries_[i].code == code)
+ return entries_[i].dynlib;
+ }
+
+ return SourceCppDynlib();
+ }
+
+ private:
+ struct Entry {
+ std::string file;
+ std::string code;
+ SourceCppDynlib dynlib;
+ };
+ std::vector<Entry> entries_;
+ };
+
+} // anonymous namespace
+
+// Create temporary build directory, generate code as necessary, and return
+// the context required for the sourceCpp function to complete it's work
+RcppExport SEXP sourceCppContext(SEXP sFile, SEXP sCode, SEXP sPlatform) {
+BEGIN_RCPP
+ // parameters
+ std::string file = Rcpp::as<std::string>(sFile);
+ std::string code = sCode != R_NilValue ? Rcpp::as<std::string>(sCode) : "";
+ Rcpp::List platform = Rcpp::as<Rcpp::List>(sPlatform);
+
+ // get dynlib (using cache if possible)
+ static SourceCppDynlibCache s_dynlibCache;
+ SourceCppDynlib dynlib;
+ if (!code.empty())
+ dynlib = s_dynlibCache.lookupByCode(code);
+ else
+ dynlib = s_dynlibCache.lookupByFile(file);
+
+ // check dynlib build state
+ bool buildRequired = false;
+
+ // if there is no dynlib in the cache then create one
+ if (dynlib.isEmpty()) {
+ buildRequired = true;
+ dynlib = SourceCppDynlib(file, platform);
+ if (!code.empty())
+ s_dynlibCache.insertCode(code, dynlib);
+ else
+ s_dynlibCache.insertFile(file, dynlib);
+ }
+
+ // if the cached dynlib is dirty then regenerate the source
+ else if (dynlib.isSourceDirty()) {
+ buildRequired = true;
+ dynlib.regenerateSource();
+ }
+
+ // if the dynlib hasn't yet been built then note that
+ else if (!dynlib.isBuilt()) {
+ buildRequired = true;
+ }
+
+ // return context as a list
+ Rcpp::List context;
+ context["moduleName"] = dynlib.moduleName();
+ context["cppSourcePath"] = dynlib.cppSourcePath();
+ context["buildRequired"] = buildRequired;
+ context["buildDirectory"] = dynlib.buildDirectory();
+ context["generatedCpp"] = dynlib.generatedCpp();
+ context["exportedFunctions"] = dynlib.exportedFunctions();
+ context["cppSourceFilename"] = dynlib.cppSourceFilename();
+ context["dynlibFilename"] = dynlib.dynlibFilename();
+ context["dynlibPath"] = dynlib.dynlibPath();
+ context["depends"] = dynlib.depends();
+ return Rcpp::wrap(context);
+END_RCPP
+}
Modified: pkg/Rcpp/src/AttributesParser.h
===================================================================
--- pkg/Rcpp/src/AttributesParser.h 2012-11-07 00:50:04 UTC (rev 3905)
+++ pkg/Rcpp/src/AttributesParser.h 2012-11-07 01:29:23 UTC (rev 3906)
@@ -23,7 +23,7 @@
#include <vector>
#include <iosfwd>
-#include <Rcpp.h>
+#include <Rcpp/Vector.h>
namespace Rcpp {
namespace attributes_parser {
More information about the Rcpp-commits
mailing list