Skip to content

Commit bd3ff3b

Browse files
committed
Fixes and updates to the attributes parser (#117)
1 parent ef428d0 commit bd3ff3b

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

ChangeLog

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2014-02-17 Kevin Ushey <[email protected]>
2+
3+
* src/attributes.cpp: Fix attributes behavior with
4+
::create, and also add an option for a default constructor
5+
(e.g. NumericVector v = NumericVector(10)) gives a default
6+
value of 'numeric(10)' at the R level). Also make NAs
7+
keep their type when exposed to R.
8+
19
2014-02-16 JJ Allaire <[email protected]>
210

311
* src/attributes.cpp Replace (incorrect) call to

inst/NEWS.Rd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
\item Changes in Rcpp Attributes
2020
\itemize{
2121
\item Fix issue preventing packages with Rcpp::interfaces attribute
22-
from compiling.
22+
from compiling.
23+
\item Fix behavior with attributes parsing of ::create for default
24+
arguments, and also allow constructors of a given size
25+
(e.g. NumericVector v = NumericVector(10)) gives a default
26+
value of 'numeric(10)' at the R level). Also make NAs preserve
27+
type when exported to R (e.g. NA_STRING as a default argument
28+
maps to NA_character_ at the R level)
2329
}
2430
}
2531
}

src/attributes.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,16 +2016,18 @@ namespace attributes {
20162016

20172017
std::string args = cppArg.substr(createLoc + create.length());
20182018
if (type == "CharacterVector")
2019-
return "character" + args;
2020-
else if (type == "IntegerVector")
2021-
return "integer" + args;
2022-
else if (type == "NumericVector")
2023-
return "numeric" + args;
2024-
else
2025-
return std::string();
2019+
return "as.character( c" + args + ")";
2020+
if (type == "IntegerVector")
2021+
return "as.integer( c" + args + ")";
2022+
if (type == "NumericVector")
2023+
return "as.numeric( c" + args + ")";
2024+
if (type == "LogicalVector")
2025+
return "as.logical( c" + args + ")";
2026+
2027+
return std::string();
20262028
}
20272029

2028-
// convert a C++ Matrix to an R argument (returns emtpy string
2030+
// convert a C++ Matrix to an R argument (returns empty string
20292031
// if no conversion possible)
20302032
std::string cppMatrixArgToRArg(const std::string& cppArg) {
20312033

@@ -2041,7 +2043,7 @@ namespace attributes {
20412043
return "matrix" + args;
20422044
}
20432045

2044-
// convert a C++ literal to an R argument (returns emtpy string
2046+
// convert a C++ literal to an R argument (returns empty string
20452047
// if no conversion possible)
20462048
std::string cppLiteralArgToRArg(const std::string& cppArg) {
20472049
if (cppArg == "true")
@@ -2050,14 +2052,46 @@ namespace attributes {
20502052
return "FALSE";
20512053
else if (cppArg == "R_NilValue")
20522054
return "NULL";
2053-
else if (cppArg == "NA_STRING" || cppArg == "NA_INTEGER" ||
2054-
cppArg == "NA_LOGICAL" || cppArg == "NA_REAL") {
2055-
return "NA";
2056-
}
2055+
else if (cppArg == "NA_STRING")
2056+
return "NA_character_";
2057+
else if (cppArg == "NA_INTEGER")
2058+
return "NA_integer_";
2059+
else if (cppArg == "NA_LOGICAL")
2060+
return "NA_integer_";
2061+
else if (cppArg == "NA_REAL")
2062+
return "NA_real_";
20572063
else
20582064
return std::string();
20592065
}
20602066

2067+
// convert an Rcpp container constructor to an R argument
2068+
// (returns empty string if no conversion possible)
2069+
std::string cppConstructorArgToRArg(const std::string& cppArg) {
2070+
2071+
// map Rcpp containers to R default initializers
2072+
static const std::map<std::string, std::string> RcppContainerToR = {
2073+
{"NumericVector", "numeric"},
2074+
{"DoubleVector", "numeric"},
2075+
{"CharacterVector", "character"},
2076+
{"IntegerVector", "integer"},
2077+
{"LogicalVector", "logical"},
2078+
{"ComplexVector", "complex"}
2079+
};
2080+
2081+
// for each entry in the map above, see if we find it; if we do,
2082+
// return the R version
2083+
typedef std::map<std::string, std::string>::const_iterator Iterator;
2084+
for (Iterator it = RcppContainerToR.begin(); it != RcppContainerToR.end(); ++it) {
2085+
size_t loc = cppArg.find(it->first);
2086+
if (loc != std::string::npos) {
2087+
return it->second + cppArg.substr(it->first.size(), std::string::npos);
2088+
}
2089+
}
2090+
2091+
return std::string();
2092+
2093+
}
2094+
20612095
// convert a C++ argument value to an R argument value (returns empty
20622096
// string if no conversion is possible)
20632097
std::string cppArgToRArg(const std::string& type,
@@ -2087,6 +2121,11 @@ namespace attributes {
20872121
if (!rArg.empty())
20882122
return rArg;
20892123

2124+
// try for a constructor arg
2125+
rArg = cppConstructorArgToRArg(cppArg);
2126+
if (!rArg.empty())
2127+
return rArg;
2128+
20902129
// couldn't parse the arg
20912130
return std::string();
20922131
}

0 commit comments

Comments
 (0)