[Rcpp-commits] r4078 - pkg/Rcpp/src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Tue Dec 4 21:01:53 CET 2012
Author: jjallaire
Date: 2012-12-04 21:01:53 +0100 (Tue, 04 Dec 2012)
New Revision: 4078
Modified:
pkg/Rcpp/src/AttributesGen.cpp
Log:
fix unused variable warning
Modified: pkg/Rcpp/src/AttributesGen.cpp
===================================================================
--- pkg/Rcpp/src/AttributesGen.cpp 2012-12-04 19:57:22 UTC (rev 4077)
+++ pkg/Rcpp/src/AttributesGen.cpp 2012-12-04 20:01:53 UTC (rev 4078)
@@ -1,727 +1,726 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
-//
-// AttributesGen.cpp: Rcpp R/C++ interface class library -- Rcpp attributes
-//
-// Copyright (C) 2012 JJ Allaire, Dirk Eddelbuettel and Romain Francois
-//
-// This file is part of Rcpp.
-//
-// Rcpp is free software: you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 2 of the License, or
-// (at your option) any later version.
-//
-// Rcpp is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
-
-#include "AttributesGen.h"
-#include "AttributesUtil.h"
-#include "AttributesTypes.h"
-
-#include <fstream>
-
-#include <Rcpp/iostream/Rostream.h>
-
-namespace Rcpp {
-namespace attributes {
-
- namespace {
- const char * const kRcppExportsSuffix = "_RcppExports.h";
-
- // Generate placeholder function declaration (for roxygen)
- void generateRoxygenPlaceholder(std::ostream& ostr,
- const Attribute& attrib) {
-
- ostr << attrib.exportedName() << "<- function(";
- const std::vector<Argument>& args = attrib.function().arguments();
- for (std::size_t i=0; i<args.size(); i++) {
- ostr << args[i].name();
- if (i != (args.size()-1))
- ostr << ", ";
- }
- ostr << ") {}" << std::endl;
- }
-
- // Generate roxygen
- void generateRoxygen(std::ostream& ostr,
- const SourceFileAttributes& attributes) {
-
- for(SourceFileAttributes::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- if (it->isExportedFunction() && !it->roxygen().empty()) {
- ostr << std::endl;
- for (std::size_t i=0; i<it->roxygen().size(); i++)
- ostr << it->roxygen()[i] << std::endl;
- generateRoxygenPlaceholder(ostr, *it);
- ostr << std::endl;
- }
- }
- }
-
- } // anonymous namespace
-
- ExportsGenerator::ExportsGenerator(const std::string& targetFile,
- const std::string& package,
- const std::string& commentPrefix)
- : targetFile_(targetFile),
- package_(package),
- commentPrefix_(commentPrefix) {
-
- // read the existing target file if it exists
- if (FileInfo(targetFile_).exists()) {
- std::ifstream ifs(targetFile_.c_str());
- if (ifs.fail())
- throw Rcpp::file_io_error(targetFile_);
- std::stringstream buffer;
- buffer << ifs.rdbuf();
- existingCode_ = buffer.str();
- }
-
- // see if this is safe to overwite and throw if it isn't
- if (!isSafeToOverwrite())
- throw Rcpp::file_exists(targetFile_);
- }
-
- // Commit the stream -- is a no-op if the existing code is identical
- // to the generated code. Returns true if data was written and false
- // if it wasn't (throws exception on io error)
- bool ExportsGenerator::commit(const std::string& preamble) {
-
- // get the generated code
- std::string code = codeStream_.str();
-
- // if there is no generated code AND the exports file does not
- // currently exist then do nothing
- if (code.empty() && !FileInfo(targetFile_).exists())
- return false;
-
- // write header/preamble
- std::ostringstream headerStream;
- headerStream << commentPrefix_ << " This file was generated by "
- << "Rcpp::compileAttributes" << std::endl;
- headerStream << commentPrefix_ << " Generator token: "
- << generatorToken() << std::endl << std::endl;
- if (!preamble.empty())
- headerStream << preamble;
-
- // get generated code and only write it if there was a change
- std::string generatedCode = headerStream.str() + code;
- if (generatedCode != existingCode_) {
- // open the file
- std::ofstream ofs(targetFile_.c_str(),
- std::ofstream::out | std::ofstream::trunc);
- if (ofs.fail())
- throw Rcpp::file_io_error(targetFile_);
-
- // write generated code and return
- ofs << generatedCode;
- ofs.close();
- return true;
- }
- else {
- return false;
- }
- }
-
- // Remove the generated file entirely
- bool ExportsGenerator::remove() {
- return removeFile(targetFile_);
- }
-
- CppExportsGenerator::CppExportsGenerator(const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "src" + fileSep + "RcppExports.cpp",
- package,
- "//")
- {
- }
-
- void CppExportsGenerator::writeBegin() {
- ostr() << "RCPP_MODULE(" << package() << "_RcppExports) {"
- << std::endl;
- }
-
- void CppExportsGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- // verbose output if requested
- if (verbose) {
- Rcpp::Rcout << "Exports from " << attributes.sourceFile() << ":"
- << std::endl;
- }
-
- // generate functions
- generateCppModuleFunctions(ostr(), attributes, verbose);
-
- // track prototypes/signatures for inclusion in the preamble
- for (std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
- if (it->isExportedFunction()) {
-
- // prototypes
- std::ostringstream ostr;
- ostr << it->function();
- prototypes_.push_back(ostr.str());
-
- // signatures
- if (!it->function().isHidden()) {
- signatures_.push_back(
- it->function().signature(it->exportedName()));
- }
- }
- }
-
- // verbose if requested
- if (verbose)
- Rcpp::Rcout << std::endl;
- }
-
- void CppExportsGenerator::writeEnd() {
-
- // add our export validation helper
- ostr() << " Rcpp::function(\""
- << exportValidationFunctionRegisteredName() << "\", &"
- << exportValidationFunction() << ");" << std::endl;
-
- ostr() << "}" << std::endl;
- }
-
- bool CppExportsGenerator::commit(const std::vector<std::string>& includes) {
-
- // includes
- std::ostringstream ostr;
- if (!includes.empty()) {
- for (std::size_t i=0;i<includes.size(); i++)
- ostr << includes[i] << std::endl;
- }
- ostr << "#include <string>" << std::endl;
- ostr << "#include <set>" << std::endl;
- ostr << std::endl;
-
- // always bring in Rcpp
- ostr << "using namespace Rcpp;" << std::endl << std::endl;
-
- // prototypes
- if (!prototypes_.empty()) {
- for (std::size_t i=0;i<prototypes_.size(); i++)
- ostr << prototypes_[i] << ";" << std::endl;
- ostr << std::endl;
- }
-
- // generate a function that can be used to validate exported
- // functions and their signatures prior to looking up with
- // GetCppCallable (otherwise inconsistent signatures between
- // client and library would cause a crash)
- ostr << "static bool " << exportValidationFunction()
- << "(const std::string& sig)" << " {" << std::endl;
- ostr << " static std::set<std::string> signatures;"
- << std::endl;
- ostr << " if (signatures.empty()) {" << std::endl;
- for (std::size_t i=0;i<signatures_.size(); i++) {
- ostr << " signatures.insert(\"" << signatures_[i]
- << "\");" << std::endl;
- }
- ostr << " }" << std::endl;
- ostr << " return signatures.find(sig) != signatures.end();"
- << std::endl;
- ostr << "}" << std::endl << std::endl;
-
- // commit with preamble
- return ExportsGenerator::commit(ostr.str());
- }
-
- CppExportsIncludeGenerator::CppExportsIncludeGenerator(
- const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "inst" + fileSep + "include" +
- fileSep + package + kRcppExportsSuffix,
- package,
- "//")
- {
- includeDir_ = packageDir + fileSep + "inst" + fileSep + "include";
- hasCppInterface_ = false;
- }
-
- void CppExportsIncludeGenerator::writeBegin() {
-
- ostr() << "namespace " << package() << " {"
- << std::endl << std::endl;
-
- // Import Rcpp into this namespace. This allows declarations to
- // be written without fully qualifying all Rcpp types. The only
- // negative side-effect is that when this package's namespace
- // is imported it will also pull in Rcpp. However since this is
- // opt-in and represents a general desire to do namespace aliasing
- // this seems okay
- ostr() << " using namespace Rcpp;" << std::endl << std::endl;
-
- // Write our export validation helper function. Putting it in
- // an anonymous namespace will hide it from callers and give
- // it per-translation unit linkage
- ostr() << " namespace {" << std::endl;
- ostr() << " void " << exportValidationFunction()
- << "(const std::string& sig) {" << std::endl;
- std::string ptrName = "p_" + exportValidationFunction();
- ostr() << " static bool(" << "*" << ptrName
- << ")(const std::string&) = "
- << getCppCallable(exportValidationFunctionRegisteredName())
- << ";" << std::endl;
- ostr() << " if (!" << ptrName << "(sig))" << std::endl;
- ostr() << " throw Rcpp::function_not_exported(\""
- << "Function '\" + sig + \"' not found in " << package()
- << "\");" << std::endl;
- ostr() << " }" << std::endl;
-
- ostr() << " }" << std::endl << std::endl;
- }
-
- void CppExportsIncludeGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
-
- // don't write anything if there is no C++ interface
- if (!attributes.hasInterface(kInterfaceCpp))
- return;
-
- // there is a C++ interface so set flag indicating so
- hasCppInterface_ = true;
-
- for(std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- if (it->isExportedFunction()) {
-
- Function function =
- it->function().renamedTo(it->exportedName());
-
- // if it's hidden then don't generate a C++ interface
- if (function.isHidden())
- continue;
-
- ostr() << " inline " << function << " {"
- << std::endl;
-
- std::string ptrName = "p_" + function.name();
- ostr() << " static " << function.signature(ptrName);
- ostr() << " = NULL;" << std::endl;
- ostr() << " if (" << ptrName << " == NULL) {"
- << std::endl;
- ostr() << " " << exportValidationFunction()
- << "(\"" << function.signature() << "\");"
- << std::endl;
- ostr() << " " << ptrName << " = "
- << getCppCallable(function.name()) << ";"
- << std::endl;
- ostr() << " }" << std::endl;
- ostr() << " return " << ptrName << "(";
-
- const std::vector<Argument>& args = function.arguments();
- for (std::size_t i = 0; i<args.size(); i++) {
- ostr() << args[i].name();
- if (i != (args.size()-1))
- ostr() << ",";
- }
-
- ostr() << ");" << std::endl;
- ostr() << " }" << std::endl << std::endl;
- }
- }
- }
-
- void CppExportsIncludeGenerator::writeEnd() {
- ostr() << "}" << std::endl;
- ostr() << std::endl;
- ostr() << "#endif // " << getHeaderGuard() << std::endl;
- }
-
- bool CppExportsIncludeGenerator::commit(
- const std::vector<std::string>& includes) {
-
- if (hasCppInterface_) {
-
- // create the include dir if necessary
- createDirectory(includeDir_);
-
- // generate preamble
- std::ostringstream ostr;
-
- // header guard
- std::string guard = getHeaderGuard();
- ostr << "#ifndef " << guard << std::endl;
- ostr << "#define " << guard << std::endl << std::endl;
-
- // includes
- if (!includes.empty()) {
- for (std::size_t i=0;i<includes.size(); i++)
- ostr << includes[i] << std::endl;
- ostr << std::endl;
- }
-
- // commit with preamble
- return ExportsGenerator::commit(ostr.str());
- }
- else {
- return ExportsGenerator::remove();
- }
- }
-
- std::string CppExportsIncludeGenerator::getCppCallable(
- const std::string& function) const {
- std::ostringstream ostr;
- ostr << "Rcpp::GetCppCallable"
- << "(\"" << package() << "\", "
- << "\"" << package() + "_RcppExports\", "
- << "\"" << function << "\")";
- return ostr.str();
- }
-
- std::string CppExportsIncludeGenerator::getHeaderGuard() const {
- return package() + "__RcppExports_h__";
- }
-
- CppPackageIncludeGenerator::CppPackageIncludeGenerator(
- const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "inst" + fileSep + "include" +
- fileSep + package + ".h",
- package,
- "//")
- {
- includeDir_ = packageDir + fileSep + "inst" + fileSep + "include";
- hasCppInterface_ = false;
- }
-
- void CppPackageIncludeGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- // See if there is a C++ interface exported by any attributes
- if (attributes.hasInterface(kInterfaceCpp))
- hasCppInterface_ = true;
- }
-
- void CppPackageIncludeGenerator::writeEnd() {
- if (hasCppInterface_) {
- // header guard
- std::string guard = getHeaderGuard();
- ostr() << "#ifndef " << guard << std::endl;
- ostr() << "#define " << guard << std::endl << std::endl;
-
- ostr() << "#include \"" << package() << kRcppExportsSuffix
- << "\"" << std::endl;
-
- ostr() << std::endl;
- ostr() << "#endif // " << getHeaderGuard() << std::endl;
- }
- }
-
- bool CppPackageIncludeGenerator::commit(
- const std::vector<std::string>& includes) {
-
- if (hasCppInterface_) {
-
- // create the include dir if necessary
- createDirectory(includeDir_);
-
- // commit
- return ExportsGenerator::commit();
- }
- else {
- return ExportsGenerator::remove();
- }
- }
-
- std::string CppPackageIncludeGenerator::getHeaderGuard() const {
- return "__" + package() + "_h__";
- }
-
- RExportsGenerator::RExportsGenerator(const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "R" + fileSep + "RcppExports.R",
- package,
- "#")
- {
- }
-
- void RExportsGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
-
- // add to exported functions if we have an R interface
- if (attributes.hasInterface(kInterfaceR)) {
-
- // track exported functions
- for (std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
- if (it->isExportedFunction()) {
- rExports_.push_back(it->exportedName());
- }
- }
-
- // generate roxygen
- generateRoxygen(ostr(), attributes);
- }
- }
-
- void RExportsGenerator::writeEnd() {
-
- ostr() << "Rcpp::loadModule(\"" << package() << "_RcppExports\", ";
- if (rExports_.size() > 0) {
- ostr() << std::endl;
- ostr() << " what = c(";
- for (size_t i=0; i<rExports_.size(); i++) {
- if (i != 0)
- ostr() << " ";
- ostr() << "\"" << rExports_[i] << "\"";
- if (i != (rExports_.size()-1))
- ostr() << "," << std::endl;
- }
- ostr() << "))" << std::endl;
- }
- else {
- ostr() << "what = character())";
- }
- }
-
- bool RExportsGenerator::commit(const std::vector<std::string>& includes) {
- return ExportsGenerator::commit();
- }
-
- ExportsGenerators::~ExportsGenerators() {
- try {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- delete *it;
- generators_.clear();
- }
- catch(...) {}
- }
-
- void ExportsGenerators::add(ExportsGenerator* pGenerator) {
- generators_.push_back(pGenerator);
- }
-
- void ExportsGenerators::writeBegin() {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeBegin();
- }
-
- void ExportsGenerators::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeFunctions(attributes, verbose);
- }
-
- void ExportsGenerators::writeEnd() {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeEnd();
- }
-
- // Commit and return a list of the files that were updated
- std::vector<std::string> ExportsGenerators::commit(
- const std::vector<std::string>& includes) {
-
- std::vector<std::string> updated;
-
- for(Itr it = generators_.begin(); it != generators_.end(); ++it) {
- if ((*it)->commit(includes))
- updated.push_back((*it)->targetFile());
- }
-
- return updated;
- }
-
- // Remove and return a list of files that were removed
- std::vector<std::string> ExportsGenerators::remove() {
- std::vector<std::string> removed;
- for(Itr it = generators_.begin(); it != generators_.end(); ++it) {
- if ((*it)->remove())
- removed.push_back((*it)->targetFile());
- }
- return removed;
- }
-
- // Generate function entries for passed attributes
- void generateCppModuleFunctions(std::ostream& ostr,
- const SourceFileAttributes& attributes,
- bool verbose)
- {
- for(std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- // verify this is an exported function
- if (it->isExportedFunction()) {
-
- // verbose output
- const Function& function = it->function();
- if (verbose)
- Rcpp::Rcout << " " << function << std::endl;
-
- // add module function export
- ostr << " Rcpp::function(\"" << it->exportedName() << "\", &"
- << function.name();
-
- // add information on arguments
- const std::vector<Argument>& args =
- it->function().arguments();
- ostr << ", Rcpp::List::create(";
- for (size_t i=0; i<args.size(); i++) {
- const Argument& arg = args[i];
- ostr << "Rcpp::Named(\"" << arg.name() << "\")";
- if (!arg.defaultValue().empty())
- ostr << " = " << arg.defaultValue();
- if (i != (args.size()-1))
- ostr << ", ";
- }
- ostr << ")";
- ostr << ");" << std::endl;
-
- }
- }
- }
-
- namespace {
- // convert a C++ numeric argument to an R argument value
- // (returns empty string if no conversion is possible)
- std::string cppNumericArgToRArg(const std::string& type,
- const std::string& cppArg) {
- // check for a number
- double num;
- std::stringstream argStream(cppArg);
- if ((argStream >> num)) {
-
- // L suffix means return the value literally
- bool isInteger = false;
- if (!argStream.eof()) {
- std::string suffix;
- argStream >> suffix;
- if (argStream.eof() && suffix == "L")
- return cppArg;
- }
-
- // no decimal and the type isn't explicitly double or
- // float means integer
- if (cppArg.find('.') == std::string::npos &&
- type != "double" && type != "float")
- return cppArg + "L";
-
- // otherwise return arg literally
- else
- return cppArg;
- }
- else {
- return std::string();
- }
- }
-
- // convert a C++ ::create style argument value to an R argument
- // value (returns empty string if no conversion is possible)
- std::string cppCreateArgToRArg(const std::string& cppArg) {
-
- std::string create = "::create";
- size_t createLoc = cppArg.find(create);
- if (createLoc == std::string::npos ||
- ((createLoc + create.length()) >= cppArg.size())) {
- return std::string();
- }
-
- std::string type = cppArg.substr(0, createLoc);
- std::string rcppScope = "Rcpp::";
- size_t rcppLoc = type.find(rcppScope);
- if (rcppLoc == 0 && type.size() > rcppScope.length())
- type = type.substr(rcppScope.length());
-
- std::string args = cppArg.substr(createLoc + create.length());
- if (type == "CharacterVector")
- return "character" + args;
- else if (type == "IntegerVector")
- return "integer" + args;
- else if (type == "NumericVector")
- return "numeric" + args;
- else
- return std::string();
- }
-
- // convert a C++ Matrix to an R argument (returns emtpy string
- // if no conversion possible)
- std::string cppMatrixArgToRArg(const std::string& cppArg) {
-
- // look for Matrix
- std::string matrix = "Matrix";
- size_t matrixLoc = cppArg.find(matrix);
- if (matrixLoc == std::string::npos ||
- ((matrixLoc + matrix.length()) >= cppArg.size())) {
- return std::string();
- }
-
- std::string args = cppArg.substr(matrixLoc + matrix.length());
- return "matrix" + args;
- }
-
- // convert a C++ literal to an R argument (returns emtpy string
- // if no conversion possible)
- std::string cppLiteralArgToRArg(const std::string& cppArg) {
- if (cppArg == "true")
- return "TRUE";
- else if (cppArg == "false")
- return "FALSE";
- else if (cppArg == "R_NilValue")
- return "NULL";
- else if (cppArg == "NA_STRING" || cppArg == "NA_INTEGER" ||
- cppArg == "NA_LOGICAL" || cppArg == "NA_REAL") {
- return "NA";
- }
- else
- return std::string();
- }
- } // anonymous namespace
-
- // convert a C++ argument value to an R argument value (returns empty
- // string if no conversion is possible)
- std::string cppArgToRArg(const std::string& type,
- const std::string& cppArg) {
-
- // try for quoted string
- if (isQuoted(cppArg))
- return cppArg;
-
- // try for literal
- std::string rArg = cppLiteralArgToRArg(cppArg);
- if (!rArg.empty())
- return rArg;
-
- // try for a create arg
- rArg = cppCreateArgToRArg(cppArg);
- if (!rArg.empty())
- return rArg;
-
- // try for a matrix arg
- rArg = cppMatrixArgToRArg(cppArg);
- if (!rArg.empty())
- return rArg;
-
- // try for a numeric arg
- rArg = cppNumericArgToRArg(type, cppArg);
- if (!rArg.empty())
- return rArg;
-
- // couldn't parse the arg
- return std::string();
- }
-
-
-} // namespace attributes
-} // namespace Rcpp
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+//
+// AttributesGen.cpp: Rcpp R/C++ interface class library -- Rcpp attributes
+//
+// Copyright (C) 2012 JJ Allaire, Dirk Eddelbuettel and Romain Francois
+//
+// This file is part of Rcpp.
+//
+// Rcpp is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 2 of the License, or
+// (at your option) any later version.
+//
+// Rcpp is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
+
+#include "AttributesGen.h"
+#include "AttributesUtil.h"
+#include "AttributesTypes.h"
+
+#include <fstream>
+
+#include <Rcpp/iostream/Rostream.h>
+
+namespace Rcpp {
+namespace attributes {
+
+ namespace {
+ const char * const kRcppExportsSuffix = "_RcppExports.h";
+
+ // Generate placeholder function declaration (for roxygen)
+ void generateRoxygenPlaceholder(std::ostream& ostr,
+ const Attribute& attrib) {
+
+ ostr << attrib.exportedName() << "<- function(";
+ const std::vector<Argument>& args = attrib.function().arguments();
+ for (std::size_t i=0; i<args.size(); i++) {
+ ostr << args[i].name();
+ if (i != (args.size()-1))
+ ostr << ", ";
+ }
+ ostr << ") {}" << std::endl;
+ }
+
+ // Generate roxygen
+ void generateRoxygen(std::ostream& ostr,
+ const SourceFileAttributes& attributes) {
+
+ for(SourceFileAttributes::const_iterator
+ it = attributes.begin(); it != attributes.end(); ++it) {
+
+ if (it->isExportedFunction() && !it->roxygen().empty()) {
+ ostr << std::endl;
+ for (std::size_t i=0; i<it->roxygen().size(); i++)
+ ostr << it->roxygen()[i] << std::endl;
+ generateRoxygenPlaceholder(ostr, *it);
+ ostr << std::endl;
+ }
+ }
+ }
+
+ } // anonymous namespace
+
+ ExportsGenerator::ExportsGenerator(const std::string& targetFile,
+ const std::string& package,
+ const std::string& commentPrefix)
+ : targetFile_(targetFile),
+ package_(package),
+ commentPrefix_(commentPrefix) {
+
+ // read the existing target file if it exists
+ if (FileInfo(targetFile_).exists()) {
+ std::ifstream ifs(targetFile_.c_str());
+ if (ifs.fail())
+ throw Rcpp::file_io_error(targetFile_);
+ std::stringstream buffer;
+ buffer << ifs.rdbuf();
+ existingCode_ = buffer.str();
+ }
+
+ // see if this is safe to overwite and throw if it isn't
+ if (!isSafeToOverwrite())
+ throw Rcpp::file_exists(targetFile_);
+ }
+
+ // Commit the stream -- is a no-op if the existing code is identical
+ // to the generated code. Returns true if data was written and false
+ // if it wasn't (throws exception on io error)
+ bool ExportsGenerator::commit(const std::string& preamble) {
+
+ // get the generated code
+ std::string code = codeStream_.str();
+
+ // if there is no generated code AND the exports file does not
+ // currently exist then do nothing
+ if (code.empty() && !FileInfo(targetFile_).exists())
+ return false;
+
+ // write header/preamble
+ std::ostringstream headerStream;
+ headerStream << commentPrefix_ << " This file was generated by "
+ << "Rcpp::compileAttributes" << std::endl;
+ headerStream << commentPrefix_ << " Generator token: "
+ << generatorToken() << std::endl << std::endl;
+ if (!preamble.empty())
+ headerStream << preamble;
+
+ // get generated code and only write it if there was a change
+ std::string generatedCode = headerStream.str() + code;
+ if (generatedCode != existingCode_) {
+ // open the file
+ std::ofstream ofs(targetFile_.c_str(),
+ std::ofstream::out | std::ofstream::trunc);
+ if (ofs.fail())
[TRUNCATED]
To get the complete diff run:
svnlook diff /svnroot/rcpp -r 4078
More information about the Rcpp-commits
mailing list