[Rcpp-commits] r4150 - in pkg/Rcpp: . src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Tue Dec 11 16:27:19 CET 2012


Author: jjallaire
Date: 2012-12-11 16:27:18 +0100 (Tue, 11 Dec 2012)
New Revision: 4150

Added:
   pkg/Rcpp/src/attributes.cpp
Removed:
   pkg/Rcpp/src/Attributes.cpp
   pkg/Rcpp/src/AttributesGen.cpp
   pkg/Rcpp/src/AttributesGen.h
   pkg/Rcpp/src/AttributesParser.cpp
   pkg/Rcpp/src/AttributesParser.h
   pkg/Rcpp/src/AttributesTypes.h
   pkg/Rcpp/src/AttributesUtil.h
Modified:
   pkg/Rcpp/ChangeLog
Log:
consolidate attributes into single file

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2012-12-11 15:21:06 UTC (rev 4149)
+++ pkg/Rcpp/ChangeLog	2012-12-11 15:27:18 UTC (rev 4150)
@@ -1,6 +1,14 @@
 2012-12-11  JJ Allaire <jj at rstudio.org>
       
         * R/Attributes.R: always print output when shared library is not created
+        * src/attributes.cpp: consolidate attributes into single file
+        * src/Attributes.cpp: consolidate attributes into single file
+        * src/AttributesGen.h: consolidate attributes into single file
+        * src/AttributesGen.cpp: consolidate attributes into single file
+        * src/AttributesParser.h: consolidate attributes into single file
+        * src/AttributesParser.cpp: consolidate attributes into single file
+        * src/AttributesTypes.h: consolidate attributes into single file
+        * src/AttributesUtil.h: consolidate attributes into single file
 
 2012-12-11 Romain Francois <romain at r-enthusiasts.com>
 

Deleted: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp	2012-12-11 15:21:06 UTC (rev 4149)
+++ pkg/Rcpp/src/Attributes.cpp	2012-12-11 15:27:18 UTC (rev 4150)
@@ -1,614 +0,0 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
-//
-// Attributes.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 <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include <fstream>
-#include <cstring>
-#include <map>
-#include <set>
-#include <algorithm>
-
-#define RCPP_NO_SUGAR
-#include <Rcpp.h>
-
-#include "AttributesGen.h"
-#include "AttributesParser.h"
-#include "AttributesUtil.h"
-
-// provide implementations for util 
-namespace Rcpp {
-namespace attributes {
-    
-    // Utility class for getting file existence and last modified time
-    FileInfo::FileInfo(const std::string& path) 
-        : path_(path), exists_(false), lastModified_(0)
-    {
-    #ifdef _WIN32
-        struct _stat buffer;
-        int result = _stat(path.c_str(), &buffer);
-    #else
-        struct stat buffer;
-        int result = stat(path.c_str(), &buffer);
-    #endif  
-        if (result != 0) {
-            if (errno == ENOENT)
-                exists_ = false;
-            else
-                throw Rcpp::file_io_error(errno, path);
-        } else {
-            exists_ = true;
-            lastModified_ = buffer.st_mtime;
-        }
-    }
-  
-    // Remove a file (call back into R for this)
-    bool removeFile(const std::string& path) {
-        if (FileInfo(path).exists()) {
-            Rcpp::Function rm = Rcpp::Environment::base_env()["file.remove"];
-            rm(path);
-            return true;
-        }
-        else {
-            return false;
-        }
-    }
-    
-    // Recursively create a directory (call back into R for this)
-    void createDirectory(const std::string& path) {
-        if (!FileInfo(path).exists()) {
-            Rcpp::Function mkdir = Rcpp::Environment::base_env()["dir.create"];
-            mkdir(path, Rcpp::Named("recursive") = true);
-        }
-    }    
-    
-     // Known whitespace chars
-    const char * const kWhitespaceChars = " \f\n\r\t\v";
-      
-    // Query whether a character is whitespace
-    bool isWhitespace(char ch) {
-        return std::strchr(kWhitespaceChars, ch) != NULL;
-    }
-    
-    // Trim a string
-    void trimWhitespace(std::string* pStr) {   
-        
-        // skip empty case
-        if (pStr->empty())
-            return;
-        
-        // trim right
-        std::string::size_type pos = pStr->find_last_not_of(kWhitespaceChars);
-        if (pos != std::string::npos)
-            pStr->erase(pos + 1);    
-            
-        // trim left
-        pos = pStr->find_first_not_of(kWhitespaceChars);
-        pStr->erase(0, pos);
-    }
-    
-    // Strip balanced quotes from around a string (assumes already trimmed)
-    void stripQuotes(std::string* pStr) {
-        if (pStr->length() < 2)
-            return;       
-        char quote = *(pStr->begin());
-        if ( (quote == '\'' || quote == '\"') && (*(pStr->rbegin()) == quote) )
-            *pStr = pStr->substr(1, pStr->length()-2);
-    }
-    
-    // is the passed string quoted?
-    bool isQuoted(const std::string& str) {
-        if (str.length() < 2)
-            return false;
-        char quote = *(str.begin());
-        return (quote == '\'' || quote == '\"') && (*(str.rbegin()) == quote);
-    }
-    
-    // show a warning message
-    void showWarning(const std::string& msg) {
-        Rcpp::Function warning = Rcpp::Environment::base_env()["warning"];     
-        warning(msg, Rcpp::Named("call.") = false);
-    }
-    
-} // namespace attributes
-} // namespace Rcpp
-
-
-using namespace Rcpp::attributes;
-
-// 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_);
-                    
-            // 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 context id
-            contextId_ = "sourceCpp_" + createRandomizer();
-            
-            // 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() {
-            
-            // create new dynlib filename
-            previousDynlibFilename_ = dynlibFilename_;
-            dynlibFilename_ = "sourceCpp_" + createRandomizer() + dynlibExt_;
-            
-            // copy the source file to the build dir
-            Rcpp::Function filecopy = Rcpp::Environment::base_env()["file.copy"];
-            filecopy(cppSourcePath_, generatedCppSourcePath(), true);
-            
-            // parse attributes
-            SourceFileAttributesParser sourceAttributes(cppSourcePath_);
-        
-            // generate cpp for attributes and append them 
-            std::ostringstream ostr;
-            // always include Rcpp.h in case the user didn't
-            ostr << std::endl << std::endl;
-            ostr << "#include <Rcpp.h>" << std::endl;
-            generateCpp(ostr, sourceAttributes, false, false, contextId_);
-            generatedCpp_ = ostr.str();
-            std::ofstream cppOfs(generatedCppSourcePath().c_str(), 
-                                 std::ofstream::out | std::ofstream::app);
-            if (cppOfs.fail())
-                throw Rcpp::file_io_error(generatedCppSourcePath());
-            cppOfs << generatedCpp_;
-            cppOfs.close();
-        
-            // generate R for attributes and write it into the build directory
-            std::ofstream rOfs(generatedRSourcePath().c_str(), 
-                               std::ofstream::out | std::ofstream::trunc);
-            if (rOfs.fail())
-                throw Rcpp::file_io_error(generatedRSourcePath());
-                
-            // DLLInfo - hide using . and ensure uniqueness using contextId
-            std::string dllInfo = "`." + contextId_ + "_DLLInfo`";
-            rOfs << dllInfo << " <- dyn.load('" << dynlibPath() << "')" 
-                 << std::endl << std::endl;
-                 
-            // Generate R functions 
-            generateR(rOfs, sourceAttributes, dllInfo);
-            
-            // remove the DLLInfo
-            rOfs << std::endl << "rm(" << dllInfo << ")" 
-                 << std::endl;
-     
-            rOfs.close();
-               
-            // discover exported functions, and dependencies
-            exportedFunctions_.clear();
-            depends_.clear();
-            for (SourceFileAttributesParser::const_iterator 
-              it = sourceAttributes.begin(); it != sourceAttributes.end(); ++it) {
-                 if (it->name() == kExportAttribute && !it->function().empty()) 
-                    exportedFunctions_.push_back(it->exportedName());
-                
-                 else if (it->name() == kDependsAttribute) {
-                     for (size_t i = 0; i<it->params().size(); ++i)
-                        depends_.push_back(it->params()[i].name());
-                 }   
-            }
-            
-            // capture embededded R
-            embeddedR_ = sourceAttributes.embeddedR();
-        }
-        
-        const std::string& contextId() const {
-            return contextId_;
-        }
-        
-        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 rSourceFilename() const {
-            return cppSourceFilename() + ".R";    
-        }
-         
-        std::string dynlibFilename() const {
-            return dynlibFilename_;
-        }
-        
-        std::string dynlibPath() const {
-            return buildDirectory_ + fileSep_ + dynlibFilename();
-        }
-        
-        std::string previousDynlibPath() const {
-            if (!previousDynlibFilename_.empty())
-                return buildDirectory_ + fileSep_ + previousDynlibFilename_;
-            else
-                return std::string();
-        }
-       
-        const std::vector<std::string>& exportedFunctions() const {
-            return exportedFunctions_;
-        }
-        
-        const std::vector<std::string>& depends() const { return depends_; };
-        
-        const std::vector<std::string>& embeddedR() const { return embeddedR_; }
-          
-    private:
-    
-        std::string generatedCppSourcePath() const {
-           return buildDirectory_ + fileSep_ + cppSourceFilename(); 
-        }
-        
-         std::string generatedRSourcePath() const {
-           return buildDirectory_ + fileSep_ + rSourceFilename(); 
-        }
-        
-        void generateR(std::ostream& ostr, 
-                       const SourceFileAttributes& attributes, 
-                       const std::string& dllInfo) const
-        {
-            // process each attribute
-            for(std::vector<Attribute>::const_iterator 
-                it = attributes.begin(); it != attributes.end(); ++it) {
-                
-                // alias the attribute and function (bail if not export)
-                const Attribute& attribute = *it;
-                if (!attribute.isExportedFunction())
-                    continue;
-                const Function& function = attribute.function();
-        
-                // export the function
-                ostr <<  attribute.exportedName()
-                     << " <- Rcpp:::sourceCppFunction("
-                     << "function(" << generateRArgList(function) << ") {}, " 
-                     << dllInfo << ", " 
-                     << "'" << contextId_ + "_" + function.name() 
-                     << "')" << std::endl;
-            }        
-                           
-        }
-        
-        std::string createRandomizer() {
-            Rcpp::Function sample = Rcpp::Environment::base_env()["sample"];
-            std::ostringstream ostr;
-            ostr << Rcpp::as<int>(sample(100000, 1));
-            return ostr.str();
-        }
-        
-    private:
-        std::string cppSourcePath_;
-        std::string generatedCpp_;
-        std::string cppSourceFilename_;
-        std::string contextId_;
-        std::string buildDirectory_;
-        std::string fileSep_;
-        std::string dynlibFilename_;
-        std::string previousDynlibFilename_;
-        std::string dynlibExt_;
-        std::vector<std::string> exportedFunctions_;
-        std::vector<std::string> depends_;
-        std::vector<std::string> embeddedR_;
-    };
-    
-    // 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
-        SourceCppDynlib* insertFile(const std::string& file, 
-                                    const SourceCppDynlib& dynlib) {
-            Entry entry;
-            entry.file = file;
-            entry.dynlib = dynlib;
-            entries_.push_back(entry);
-            return &(entries_.rbegin()->dynlib);
-        }
-        
-        // Insert into cache by code
-        SourceCppDynlib* insertCode(const std::string& code, 
-                                    const SourceCppDynlib& dynlib) {
-            Entry entry;
-            entry.code = code;
-            entry.dynlib = dynlib;
-            entries_.push_back(entry);
-            return &(entries_.rbegin()->dynlib);
-        }
-    
-        // 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 NULL;
-        }
-        
-        // 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 NULL;
-        }
-      
-    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* pDynlib = !code.empty() ? s_dynlibCache.lookupByCode(code) 
-                                             : s_dynlibCache.lookupByFile(file);
-   
-    // check dynlib build state
-    bool buildRequired = false;
-    
-    // if there is no dynlib in the cache then create one
-    if (pDynlib == NULL) {   
-        buildRequired = true;
-        SourceCppDynlib newDynlib(file, platform);
-        if (!code.empty())
-            pDynlib = s_dynlibCache.insertCode(code, newDynlib);
-        else
-            pDynlib = s_dynlibCache.insertFile(file, newDynlib);
-    }    
-        
-    // if the cached dynlib is dirty then regenerate the source
-    else if (pDynlib->isSourceDirty()) {
-        buildRequired = true;    
-        pDynlib->regenerateSource();
-    }
-    
-    // if the dynlib hasn't yet been built then note that
-    else if (!pDynlib->isBuilt()) {
-        buildRequired = true; 
-    }
-    
-    // return context as a list
-    using namespace Rcpp;
-    return List::create(
-        _["contextId"] = pDynlib->contextId(),
-        _["cppSourcePath"] = pDynlib->cppSourcePath(),
-        _["buildRequired"] = buildRequired,
-        _["buildDirectory"] = pDynlib->buildDirectory(),
-        _["generatedCpp"] = pDynlib->generatedCpp(),
-        _["exportedFunctions"] = pDynlib->exportedFunctions(),
-        _["cppSourceFilename"] = pDynlib->cppSourceFilename(),
-        _["rSourceFilename"] = pDynlib->rSourceFilename(),
-        _["dynlibFilename"] = pDynlib->dynlibFilename(),
-        _["dynlibPath"] = pDynlib->dynlibPath(),
-        _["previousDynlibPath"] = pDynlib->previousDynlibPath(),
-        _["depends"] = pDynlib->depends(),
-        _["embeddedR"] = pDynlib->embeddedR());
-END_RCPP
-}
-
-// Compile the attributes within the specified package directory into 
-// RcppExports.cpp and RcppExports.R
-RcppExport SEXP compileAttributes(SEXP sPackageDir, 
-                                  SEXP sPackageName,
-                                  SEXP sDepends,
-                                  SEXP sCppFiles,
-                                  SEXP sCppFileBasenames,
-                                  SEXP sIncludes,
-                                  SEXP sVerbose,
-                                  SEXP sPlatform) {
-BEGIN_RCPP
-    // arguments
-    std::string packageDir = Rcpp::as<std::string>(sPackageDir);
-    std::string packageName = Rcpp::as<std::string>(sPackageName);
-    
-    Rcpp::CharacterVector vDepends = Rcpp::as<Rcpp::CharacterVector>(sDepends);   
-    std::set<std::string> depends;
-    for (Rcpp::CharacterVector::iterator 
-                        it = vDepends.begin(); it != vDepends.end(); ++it) {
-        depends.insert(std::string(*it));
-    }
-
-    std::vector<std::string> cppFiles = 
-                    Rcpp::as<std::vector<std::string> >(sCppFiles);
-    std::vector<std::string> cppFileBasenames = 
-                    Rcpp::as<std::vector<std::string> >(sCppFileBasenames);
-    std::vector<std::string> includes = 
-                    Rcpp::as<std::vector<std::string> >(sIncludes);
-    bool verbose = Rcpp::as<bool>(sVerbose);
-    Rcpp::List platform = Rcpp::as<Rcpp::List>(sPlatform);
-    std::string fileSep = Rcpp::as<std::string>(platform["file.sep"]); 
-     
-    // initialize generators
-    ExportsGenerators generators;
-    generators.add(new CppExportsGenerator(packageDir, packageName, fileSep));
-    generators.add(new RExportsGenerator(packageDir, packageName, fileSep));
-    
-    // catch file exists exception if the include file already exists
-    // and we are unable to overwrite it
-    try {
-        generators.add(new CppExportsIncludeGenerator(packageDir, 
-                                                      packageName, 
-                                                      fileSep));
-    }
-    catch(const Rcpp::file_exists& e) {
-        std::string msg = 
-            "The header file '" + e.filePath() + "' already exists so "
-            "cannot be overwritten by Rcpp::interfaces";
-        throw Rcpp::exception(msg.c_str(), __FILE__, __LINE__);
-    }
-    
-    // catch file exists exception for package include (because if it 
-    // already exists we simply leave it alone)
-    try {
-        generators.add(new CppPackageIncludeGenerator(packageDir, 
-                                                      packageName, 
-                                                      fileSep));
-    }
-    catch(const Rcpp::file_exists& e) {}
-    
-    // write begin
-    generators.writeBegin();
-     
-    // Parse attributes from each file and generate code as required. 
-    bool haveAttributes = false;
-    std::set<std::string> dependsAttribs;
-    for (std::size_t i=0; i<cppFiles.size(); i++) {
-        
-        // parse attributes (continue if there are none)
-        std::string cppFile = cppFiles[i];
-        SourceFileAttributesParser attributes(cppFile);
-        if (attributes.empty())
-            continue;
-            
-        // confirm we have attributes
-        haveAttributes = true;
-               
-        // write functions
-        generators.writeFunctions(attributes, verbose);
-        
-        // track depends
-        for (SourceFileAttributesParser::const_iterator 
-                     it = attributes.begin(); it != attributes.end(); ++it) {
-            if (it->name() == kDependsAttribute) {
-                for (size_t i = 0; i<it->params().size(); ++i)
-                    dependsAttribs.insert(it->params()[i].name());
-            }   
-        }
-    }
-    
-    // write end
-    generators.writeEnd();
-
-    // commit or remove
-    std::vector<std::string> updated;
-    if (haveAttributes)
-        updated = generators.commit(includes);  
-    else
-        updated = generators.remove();
-           
-    // print warning if there are depends attributes that don't have 
-    // corresponding entries in the DESCRIPTION file
-    std::vector<std::string> diff;
-    std::set_difference(dependsAttribs.begin(), dependsAttribs.end(),
-                        depends.begin(), depends.end(), 
-                        std::back_inserter(diff));
-    if (!diff.empty()) {
-        std::string msg = 
-           "The following packages are referenced using Rcpp::depends "
-           "attributes however are not listed in the Depends and LinkingTo "
-           "fields of the package DESCRIPTION file: ";
-        for (size_t i=0; i<diff.size(); i++) {
-            msg += diff[i];
-            if (i != (diff.size()-1))
-                msg += ", ";
-        }
-        showWarning(msg);
-    }
-           
-    // verbose output
-    if (verbose) {
-        for (size_t i=0; i<updated.size(); i++)
-            Rcpp::Rcout << updated[i] << " updated." << std::endl;
-    }
-    
-    // return files updated
-    return Rcpp::wrap<std::vector<std::string> >(updated);
-END_RCPP
-}
-

Deleted: pkg/Rcpp/src/AttributesGen.cpp
===================================================================
--- pkg/Rcpp/src/AttributesGen.cpp	2012-12-11 15:21:06 UTC (rev 4149)
+++ pkg/Rcpp/src/AttributesGen.cpp	2012-12-11 15:27:18 UTC (rev 4150)
@@ -1,874 +0,0 @@
-// -*- 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>
-#include <Rcpp/exceptions.h>
-
-namespace Rcpp {
-namespace attributes {
-    
-    // constants
-    namespace {
-        const char * const kRcppExportsSuffix = "_RcppExports.h";
-        const char * const kTrySuffix = "_try";
-    } 
-    
-    ExportsGenerator::ExportsGenerator(const std::string& targetFile, 
-                                       const std::string& package,
-                                       const std::string& commentPrefix)
-        : targetFile_(targetFile), 
-          package_(package),
-          commentPrefix_(commentPrefix),
-          hasCppInterface_(false) {
-        
-        // 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_);
-    }
-    
-    void ExportsGenerator::writeFunctions(
-                                const SourceFileAttributes& attributes,
-                                bool verbose) {
-        
-        if (attributes.hasInterface(kInterfaceCpp))
-            hasCppInterface_ = true;
-            
-        doWriteFunctions(attributes, verbose);                                
-    }
-    
-    // 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::doWriteFunctions(
-                                 const SourceFileAttributes& attributes,
-                                 bool verbose) {
-        
-        // generate functions
-        generateCpp(ostr(), 
-                    attributes, 
-                    true, 
-                    attributes.hasInterface(kInterfaceCpp),
-                    package());
-         
-        // track cppExports and signatures (we use these at the end to
-        // generate the ValidateSignature and RegisterCCallable functions)
-        if (attributes.hasInterface(kInterfaceCpp)) {
-            for (SourceFileAttributes::const_iterator 
-                       it = attributes.begin(); it != attributes.end(); ++it) {
-                if (it->isExportedFunction()) {
-                    // add it to the list if it's not hidden
-                    Function fun = it->function().renamedTo(it->exportedName());
-                    if (!fun.isHidden())
-                        cppExports_.push_back(*it);
-                }
-            }
-        }
-     
-        // verbose if requested
-        if (verbose) {
-            Rcpp::Rcout << "Exports from " << attributes.sourceFile() << ":" 
-                        << std::endl;
-            for (std::vector<Attribute>::const_iterator 
-                    it = attributes.begin(); it != attributes.end(); ++it) {
-                if (it->isExportedFunction())
-                    Rcpp::Rcout << "   " << it->function() << std::endl; 
-            }
-            Rcpp::Rcout << std::endl;   
-        }
-    }
-    
-    void CppExportsGenerator::writeEnd()
-    {
-        // 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)
-        if (hasCppInterface()) {
-            
-            ostr() << std::endl;
-            ostr() << "// validate"
-                   << " (ensure exported C++ functions exist before "
-                   << "calling them)" << std::endl;
-            ostr() << "static int " << exportValidationFunctionRegisteredName()
-                   << "(const char* 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<cppExports_.size(); i++) {
-                const Attribute& attr = cppExports_[i];
-                ostr() << "        signatures.insert(\"" 
-                       << attr.function().signature(attr.exportedName())
-                       << "\");" << std::endl;
-            }
-            ostr() << "    }" << std::endl;
-            ostr() << "    return signatures.find(sig) != signatures.end();"
-                   << std::endl;
-            ostr() << "}" << std::endl;   
-            
-            // generate a function that will register all of our C++ 
-            // exports as C-callable from other packages
-            ostr() << std::endl;
-            ostr() << "// registerCCallable (register entry points for "
-                      "exported C++ functions)" << std::endl;
-            ostr() << "RcppExport SEXP " << registerCCallableExportedName()
-                   << "() { " << std::endl;
-            for (std::size_t i=0;i<cppExports_.size(); i++) {
-                const Attribute& attr = cppExports_[i];
-                std::string name = package() + "_" + attr.exportedName();
-                ostr() << registerCCallable(
-                              4, 
-                              attr.exportedName(),
-                              attr.function().name() + kTrySuffix);
-                ostr() << std::endl;
-            }
-            ostr() << registerCCallable(4, 
-                                        exportValidationFunction(),
-                                        exportValidationFunction());
-            ostr() << std::endl;
-            ostr() << "    return R_NilValue;" << std::endl;
-            ostr() << "}" << std::endl;
-         }
-    }
-    
-    std::string CppExportsGenerator::registerCCallable(
-                                        size_t indent,
-                                        const std::string& exportedName,
[TRUNCATED]

To get the complete diff run:
    svnlook diff /svnroot/rcpp -r 4150


More information about the Rcpp-commits mailing list