[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