[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