[Rprotobuf-commits] r735 - in pkg: . R inst/unitTests src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Thu Jan 9 22:11:39 CET 2014


Author: murray
Date: 2014-01-09 22:11:39 +0100 (Thu, 09 Jan 2014)
New Revision: 735

Modified:
   pkg/ChangeLog
   pkg/R/00classes.R
   pkg/R/read.R
   pkg/inst/unitTests/runit.addressbook.R
   pkg/src/wrapper_Descriptor.cpp
Log:
Add a logical argument 'partial' to readASCII that allows one to read
in incomplete message types in ASCII format.



Modified: pkg/ChangeLog
===================================================================
--- pkg/ChangeLog	2014-01-09 14:56:40 UTC (rev 734)
+++ pkg/ChangeLog	2014-01-09 21:11:39 UTC (rev 735)
@@ -1,3 +1,10 @@
+2014-01-09  Murray Stokely  <mstokely at google.com>
+
+	* R/read.R: Add a logical argument 'partial' to readASCII that
+	  accepts uninitialized message fragments.
+	* src/wrapper_Descriptor.cpp (rprotobuf): Idem
+	* inst/unitTests/runit.addressbook.R (test.ascii): Add tests for above.
+
 2014-01-04  Murray Stokely  <mstokely at google.com>
 
 	* R/wrapper_CodedInputStream.R: Accept numeric size arguments for

Modified: pkg/R/00classes.R
===================================================================
--- pkg/R/00classes.R	2014-01-09 14:56:40 UTC (rev 734)
+++ pkg/R/00classes.R	2014-01-09 21:11:39 UTC (rev 735)
@@ -203,7 +203,7 @@
 	switch( name,
 		"new" = function( ... ) newProto( x, ... ) ,
 		"read" = function( input ) read( x, input ) ,
-		"readASCII" = function( input ) readASCII( x, input ),
+		"readASCII" = function(input, ...) readASCII(x, input, ...),
 		"toString" = function(...) toString(x, ...) ,
 		"as.character" = function(...) as.character(x, ...) ,
 		"as.list" = function(...) as.list(x, ...) ,

Modified: pkg/R/read.R
===================================================================
--- pkg/R/read.R	2014-01-09 14:56:40 UTC (rev 734)
+++ pkg/R/read.R	2014-01-09 21:11:39 UTC (rev 735)
@@ -29,24 +29,28 @@
 
 
 
-setGeneric( "readASCII", function( descriptor, input ){
+setGeneric( "readASCII", function( descriptor, input, partial=FALSE ){
 	standardGeneric( "readASCII" )
 } )
 
 setMethod( "readASCII", c( descriptor = "Descriptor" , input = "character" ),
-function(descriptor, input ){
-	.Call( "Descriptor__readASCIIFromString", descriptor at pointer, input, PACKAGE = "RProtoBuf" )
+function(descriptor, input, partial=FALSE){
+        stopifnot(is.logical(partial), length(partial) == 1)
+	.Call( "Descriptor__readASCIIFromString", descriptor at pointer, input,
+              partial, PACKAGE = "RProtoBuf" )
 } )
 
 setMethod( "readASCII", c( descriptor = "Descriptor" ),
-function( descriptor, input ){
+function( descriptor, input, partial=FALSE){
+        stopifnot(is.logical(partial), length(partial) == 1)
 	if( !inherits( input, "connection" ) ){
 		stop( "can only read from connections" )
 	}
 	wasopen <- identical( summary(input)[["opened"]], "opened" )
 	if( !wasopen ) open( input, "rb" )
         stopifnot(summary(input)[["text"]] == "binary")
-	message <- .Call( "Descriptor__readASCIIFromConnection", descriptor at pointer, input, PACKAGE = "RProtoBuf" )
+	message <- .Call( "Descriptor__readASCIIFromConnection", descriptor at pointer, input,
+                         partial, PACKAGE = "RProtoBuf" )
 	if( !wasopen ) close( input )
 	message
 } )

Modified: pkg/inst/unitTests/runit.addressbook.R
===================================================================
--- pkg/inst/unitTests/runit.addressbook.R	2014-01-09 14:56:40 UTC (rev 734)
+++ pkg/inst/unitTests/runit.addressbook.R	2014-01-09 21:11:39 UTC (rev 735)
@@ -66,4 +66,16 @@
     # Verify that we get an exception if we forget the file() and thus treat the
     # path as a protobuf string.
     checkException( readASCII( tutorial.AddressBook, out.file2))
+
+    incomplete.msg <- new(tutorial.Person, name="Murray", email="murray at stokely.org")
+    tmp.file <- tempfile()
+    writeLines(as.character(incomplete.msg), file(tmp.file))
+
+    checkTrue(!incomplete.msg$isInitialized())
+    # Verify we normally get an exception if we try to read an incomplete ASCII protocol buffer
+    checkException( tutorial.Person$readASCII(file(tmp.file)))
+
+    # Verify we can however read it if we set partial=TRUE.
+    new.msg <- tutorial.Person$readASCII(file(tmp.file), TRUE)
+    checkEquals(incomplete.msg$name, new.msg$name)
 }

Modified: pkg/src/wrapper_Descriptor.cpp
===================================================================
--- pkg/src/wrapper_Descriptor.cpp	2014-01-09 14:56:40 UTC (rev 734)
+++ pkg/src/wrapper_Descriptor.cpp	2014-01-09 21:11:39 UTC (rev 735)
@@ -173,18 +173,31 @@
     return (S4_Message(message));
 }
 
-RPB_FUNCTION_2(S4_Message, METHOD(readASCIIFromString), Rcpp::XPtr<GPB::Descriptor> desc,
-               std::string input) {
+RPB_FUNCTION_3(S4_Message, METHOD(readASCIIFromString), Rcpp::XPtr<GPB::Descriptor> desc,
+               std::string input, bool partial) {
     GPB::Message* message = PROTOTYPE(desc);
-    if (GPB::TextFormat::ParseFromString(input, message)) {
-        return (S4_Message(message));
+    if (partial) {
+        // Allow partial messages where object is not fully initialized
+        GPB::TextFormat::Parser parser;
+        parser.AllowPartialMessage(partial);
+        if (parser.ParseFromString(input, message)) {
+            return (S4_Message(message));
+        } else {
+            throw std::range_error("Could not parse ASCII protocol buffer from text string."
+                                   " Consider setting partial=TRUE");
+        }
     } else {
-        throw std::range_error("Could not parse ASCII protocol buffer from text string.");
+        // Default parser requires fully initialized ascii messages.
+        if (GPB::TextFormat::ParseFromString(input, message)) {
+            return (S4_Message(message));
+        } else {
+            throw std::range_error("Could not parse ASCII protocol buffer from text string.");
+        }
     }
 }
 
 RPB_FUNCTION_2(S4_Message, METHOD(readASCIIFromConnection), Rcpp::XPtr<GPB::Descriptor> desc,
-               int conn_id) {
+               int conn_id, bool partial) {
     RconnectionCopyingInputStream wrapper(conn_id);
     GPB::io::CopyingInputStreamAdaptor stream(&wrapper);
 
@@ -193,14 +206,23 @@
     if (!message) {
         throw std::range_error("could not call factory->GetPrototype(desc)->New()");
     }
-    if (!GPB::TextFormat::Parse(&stream, message)) {
-        throw std::range_error("Could not parse ASCII protocol buffer.");
+    if (partial) {
+        // Allow partial messages where object is not fully initialized
+        GPB::TextFormat::Parser parser;
+        parser.AllowPartialMessage(partial);
+        if (!parser.Parse(&stream, message)) {
+            throw std::range_error("Could not parse ASCII protocol buffer.");
+        }
     } else {
-        if (wrapper.Failure()) {
-            throw std::range_error("Could not read ASCII protocol buffer.");
+        // Default parser requires fully initialized ascii messages.
+        if (!GPB::TextFormat::Parse(&stream, message)) {
+            throw std::range_error("Could not parse ASCII protocol buffer.");
         }
-        return (S4_Message(message));
     }
+    if (wrapper.Failure()) {
+        throw std::range_error("Could not read ASCII protocol buffer.");
+    }
+    return (S4_Message(message));
 }
 
 #undef METHOD



More information about the Rprotobuf-commits mailing list