[Rprotobuf-commits] r517 - in pkg: . R inst/unitTests src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Fri Aug 30 03:36:35 CEST 2013
Author: murray
Date: 2013-08-30 03:36:34 +0200 (Fri, 30 Aug 2013)
New Revision: 517
Modified:
pkg/ChangeLog
pkg/R/zzz.R
pkg/inst/unitTests/runit.int64.R
pkg/src/extractors.cpp
pkg/src/mutators.cpp
Log:
Make the code more concise by introducing a few templated functions
and rename the option name to include a packagename prefix.
Modified: pkg/ChangeLog
===================================================================
--- pkg/ChangeLog 2013-08-28 01:13:35 UTC (rev 516)
+++ pkg/ChangeLog 2013-08-30 01:36:34 UTC (rev 517)
@@ -1,3 +1,12 @@
+2013-08-29 Murray Stokely <murray at FreeBSD.org>
+
+ * R/zzz.R (.onLoad): Rename option controlling int64 handling with
+ package name prefix.
+ * inst/unitTests/runit.int64.R (test.int64): Idem
+ * src/extractors.cpp (rprotobuf): Add templated function to reduce
+ code duplication in last changelist.
+ * src/mutators.cpp (rprotobuf): Idem
+
2013-08-27 Murray Stokely <murray at FreeBSD.org>
* src/extractors.cpp (rprotobuf): Add support for a new
Modified: pkg/R/zzz.R
===================================================================
--- pkg/R/zzz.R 2013-08-28 01:13:35 UTC (rev 516)
+++ pkg/R/zzz.R 2013-08-30 01:36:34 UTC (rev 517)
@@ -5,7 +5,7 @@
##.Call( "check_libprotobuf_version", minversion, PACKAGE = "RProtoBuf" )
readProtoFiles( package=pkgname, lib.loc=libname )
attachDescriptorPool( pos = length(search()) )
- options("int64AsString" = FALSE)
+ options("RProtoBuf.int64AsString" = FALSE)
if( exists( ".httpd.handlers.env", asNamespace( "tools" ) ) ){
e <- tools:::.httpd.handlers.env
e[["RProtoBuf"]] <- RProtoBuf.http.handler
Modified: pkg/inst/unitTests/runit.int64.R
===================================================================
--- pkg/inst/unitTests/runit.int64.R 2013-08-28 01:13:35 UTC (rev 516)
+++ pkg/inst/unitTests/runit.int64.R 2013-08-30 01:36:34 UTC (rev 517)
@@ -46,7 +46,7 @@
# By default, when they are read as numerics, only 1 unique value
checkEquals(length(unique(a$repeated_int64)), 1)
- options("int64AsString" = TRUE)
+ options("RProtoBuf.int64AsString" = TRUE)
# But we can see they are different if we treat them as strings.
checkEquals(length(unique(a$repeated_int64)), 2)
}
Modified: pkg/src/extractors.cpp
===================================================================
--- pkg/src/extractors.cpp 2013-08-28 01:13:35 UTC (rev 516)
+++ pkg/src/extractors.cpp 2013-08-30 01:36:34 UTC (rev 517)
@@ -24,49 +24,31 @@
namespace rprotobuf{
-SEXP kInt64AsStringOptionName = Rf_install("int64AsString");
+const char * kIntStringOptionName = "RProtoBuf.int64AsString";
+bool UseStringsForInt64() {
+ static const SEXP option_name = Rf_install(kIntStringOptionName);
+ return (Rf_asLogical(Rf_GetOption1(option_name)));
+}
// Rcpp::wrap silently coerces 64-bit integers to numerics
// which drop precision for values between 2^53 - 2^64.
// So, if an option is set, we return as a character string.
-// TODO(mstokely): Do more of this in Rcpp.
-SEXP PreciseRInt64Type(int64 val) {
- if (Rf_asLogical(Rf_GetOption1(kInt64AsStringOptionName))) {
- std::stringstream ss;
- if ((ss << val).fail()) {
- // This should not happen, its a bug in the code.
- throwException(
- "Error converting int64 to STRSXP, unset int64AsString option.",
- "ConversionException");
+template<typename ValueType>
+SEXP Int64AsSEXP(ValueType value) {
+ if (UseStringsForInt64()) {
+ std::stringstream ss;
+ if ((ss << value).fail()) {
+ // This should not happen, its a bug in the code.
+ string message = string("Error converting int64 to string, unset ") +
+ kIntStringOptionName + " option.";
+ throwException(message.c_str(), "ConversionException");
}
- // Rcpp::wrap of the string returns vector of single characters.
- // So we must create this vector first to wrap.
- std::vector<string> retlist;
- retlist.push_back(ss.str());
- return Rcpp::wrap(retlist);
- } else {
- return Rcpp::wrap(val);
- }
+ return Rcpp::CharacterVector(ss.str());
+ } else {
+ return Rcpp::wrap(value);
+ }
}
-SEXP PreciseRUInt64Type(uint64 val) {
- if (Rf_asLogical(Rf_GetOption1(kInt64AsStringOptionName))) {
- std::stringstream ss;
- if ((ss << val).fail()) {
- // This should not happen, its a bug in the code.
- throwException(
- "Error converting uint64 to STRSXP, unset int64AsString option.",
- "ConversionException");
- }
- // Wrap the string version of this int64.
- std::vector<string> retlist;
- retlist.push_back(ss.str());
- return Rcpp::wrap(retlist);
- } else {
- return Rcpp::wrap(val);
- }
-}
-
/**
* extract a field from a message
*
@@ -123,7 +105,7 @@
// We can't handle these the same way, because Rcpp::wrap silently
// casts int64s to doubles which may cause us to lose precision.
case CPPTYPE_INT64:
- if (Rf_asLogical(Rf_GetOption1(kInt64AsStringOptionName))) {
+ if (UseStringsForInt64()) {
return Rcpp::wrap(
Int64AsStringRepeatedFieldImporter(ref, *message,
fieldDesc));
@@ -132,7 +114,7 @@
RepeatedFieldImporter<int64>(ref, *message, fieldDesc));
}
case CPPTYPE_UINT64:
- if (Rf_asLogical(Rf_GetOption1(kInt64AsStringOptionName))) {
+ if (UseStringsForInt64()) {
return Rcpp::wrap(
UInt64AsStringRepeatedFieldImporter(ref, *message,
fieldDesc));
@@ -180,9 +162,9 @@
// Handle these types separately since Rcpp::wrap doesn't
// do the right thing.
case CPPTYPE_INT64:
- return PreciseRInt64Type(ref->GetInt64(*message, fieldDesc));
+ return Int64AsSEXP<int64>(ref->GetInt64(*message, fieldDesc));
case CPPTYPE_UINT64:
- return PreciseRUInt64Type(ref->GetUInt64(*message, fieldDesc));
+ return Int64AsSEXP<uint64>(ref->GetUInt64(*message, fieldDesc));
#endif
#undef HANDLE_SINGLE_FIELD
Modified: pkg/src/mutators.cpp
===================================================================
--- pkg/src/mutators.cpp 2013-08-28 01:13:35 UTC (rev 516)
+++ pkg/src/mutators.cpp 2013-08-30 01:36:34 UTC (rev 517)
@@ -99,6 +99,17 @@
return (int32)0 ; // -Wall, should not happen since we only call this when we know it works
}
+template<typename ValueType>
+ValueType Int64FromString(const string value) {
+ std::stringstream ss(value);
+ ValueType ret;
+ if ((ss >> ret).fail() || !(ss>>std::ws).eof()) {
+ string message = "Provided character value '" + value +
+ "' cannot be cast to 64-bit integer.";
+ throwException(message.c_str(), "CastException");
+ }
+ return ret;
+}
int64 GET_int64( SEXP x, int index ){
switch( TYPEOF(x) ){
@@ -110,16 +121,8 @@
return( (int64)LOGICAL(x)[index] );
case RAWSXP:
return( (int64)RAW(x)[index] ) ;
- case STRSXP: {
- const string int64str = CHAR(STRING_ELT(x, index));
- std::stringstream ss(int64str);
- int64 ret;
- if ((ss >> ret).fail() || !(ss>>std::ws).eof()) {
- throwException("Provided STRSXP cannot be cast to int64",
- "CastException");
- }
- return ret;
- }
+ case STRSXP:
+ return Int64FromString<int64>(CHAR(STRING_ELT(x, index)));
default:
throwException( "cannot cast SEXP to int64", "CastException" ) ;
}
@@ -152,16 +155,8 @@
return( (uint64)LOGICAL(x)[index] );
case RAWSXP:
return( (uint64)RAW(x)[index] ) ;
- case STRSXP: {
- const string int64str = CHAR(STRING_ELT(x, index));
- std::stringstream ss(int64str);
- uint64 ret;
- if ((ss >> ret).fail() || !(ss>>std::ws).eof()) {
- throwException(" Provided STRSXP cannot be cast to uint64",
- "CastException");
- }
- return ret;
- }
+ case STRSXP:
+ return Int64FromString<uint64>(CHAR(STRING_ELT(x, index)));
default:
throwException( "cannot cast SEXP to uint64", "CastException" ) ;
}
@@ -1042,14 +1037,8 @@
if (TYPEOF(value) == STRSXP) {
const string int64str = COPYSTRING(CHAR(
STRING_ELT(value, 0)));
- std::stringstream ss(int64str);
- GPB::int64 ret;
- if ((ss >> ret).fail() || !(ss>>std::ws).eof()) {
- throwException(
- "Provided STRSXP cannot be cast to int64",
- "CastException");
- }
- ref->SetInt64(message, field_desc, ret);
+ ref->SetInt64(message, field_desc,
+ Int64FromString<GPB::int64>(int64str));
break ;
} else {
ref->SetInt64( message, field_desc, Rcpp::as<GPB::int64>(value));
@@ -1064,14 +1053,8 @@
if (TYPEOF(value) == STRSXP) {
const string int64str = COPYSTRING(CHAR(
STRING_ELT(value, 0)));
- std::stringstream ss(int64str);
- GPB::uint64 ret;
- if ((ss >> ret).fail() || !(ss>>std::ws).eof()) {
- throwException(
- "Provided STRSXP cannot be cast to uint64",
- "CastException");
- }
- ref->SetUInt64(message, field_desc, ret);
+ ref->SetUInt64(message, field_desc,
+ Int64FromString<GPB::uint64>(int64str));
break ;
} else {
ref->SetUInt64(message, field_desc,
More information about the Rprotobuf-commits
mailing list