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

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Thu Jul 11 10:05:00 CEST 2013


Author: murray
Date: 2013-07-11 10:05:00 +0200 (Thu, 11 Jul 2013)
New Revision: 500

Added:
   pkg/R/extensions.R
   pkg/inst/unitTests/runit.extensions.R
   pkg/src/extensions.cpp
Modified:
   pkg/ChangeLog
   pkg/NAMESPACE
   pkg/R/00classes.R
   pkg/R/completion.R
   pkg/R/set.R
   pkg/TODO
   pkg/src/DescriptorPoolLookup.cpp
   pkg/src/lookup.cpp
   pkg/src/rprotobuf.h
   pkg/src/wrapper_FileDescriptor.cpp
Log:
Add initial support for protocol buffer extensions.  This is my second
implementation, which is I think more faithful to Kenton's suggestions,
but it still needs more review and testing of edge cases.  The tests
show how this works for the basic scalar and repeated cases.



Modified: pkg/ChangeLog
===================================================================
--- pkg/ChangeLog	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/ChangeLog	2013-07-11 08:05:00 UTC (rev 500)
@@ -1,3 +1,21 @@
+2013-07-11  Murray Stokely  <murray at FreeBSD.org>
+
+	* R/extensions.R: Implement getExtension, setExtension methods.
+	* src/extensions.cpp: Implement getExtension, setExtension.
+	* R/set.R: Add a TODO noting these functions are undocumented.
+	* R/00classes.R: Add setExtension, getExtension extractors for
+	  message objects.
+	* R/completion.R: Add setExtension, getExtension.
+	* NAMESPACE: Add setExtension, getExtension.
+	* src/DescriptorPoolLookup.cpp: Add top-level
+	  extensions to descriptor pool.
+	* src/rprotobuf.h: Add helper function for getting field
+	  descriptor objects.
+	* src/wrapper_FileDescriptor.cpp: Add support for
+	  extensions to getMemberNames and as_list
+	* src/lookup.cpp: Add support for looking up extensions.
+	* inst/unitTests/runit.extensions.R: Add basic test for the above.
+
 2013-07-10  Murray Stokely  <murray at FreeBSD.org>
 
 	* man/aslist.Rd: Document behavior for enum and file descriptors

Modified: pkg/NAMESPACE
===================================================================
--- pkg/NAMESPACE	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/NAMESPACE	2013-07-11 08:05:00 UTC (rev 500)
@@ -39,8 +39,9 @@
 	"descriptor", "set", "fetch", "toString",
 	"identical", "==", "!=", "all.equal", "add",
 	"fileDescriptor", "name", "flush", "close", 
+        "setExtension", "getExtension",
 
-	"containing_type",
+        "containing_type",
 	"field_count", "nested_type_count", "enum_type_count",
 	"field", "nested_type", "enum_type",
 

Modified: pkg/R/00classes.R
===================================================================
--- pkg/R/00classes.R	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/R/00classes.R	2013-07-11 08:05:00 UTC (rev 500)
@@ -169,6 +169,8 @@
 		"as.character" = function() as.character(x),
 		"as.list" = function() as.list(x),
 		"asMessage" = function() asMessage(x),
+		"setExtension" = function(field, values, ...) setExtension(x, field, values, ...),
+		"getExtension" = function(field, ...) getExtension(x, field, ...),
 		"set" = function(...) set( x, ... ),
 		"fetch" = function(...) fetch(x, ... ),
 		"toString" = function(...) toString( x, ... ),

Modified: pkg/R/completion.R
===================================================================
--- pkg/R/completion.R	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/R/completion.R	2013-07-11 08:05:00 UTC (rev 500)
@@ -19,7 +19,8 @@
 		"has(", "clone()", "clone(", "isInitialized()", "serialize(", 
 		"clear()", "clear(", "size(", "bytesize()", 
 		"swap(", "str()", "as.character()", "update(", "as.list()", 
-		"descriptor()", "set(", "toString(", "add(", "fileDescriptor()" )
+                "setExtension(", "getExtension(",
+                "descriptor()", "set(", "toString(", "add(", "fileDescriptor()" )
 	grep( pattern, names, value = TRUE )
 }
 # }}}

Added: pkg/R/extensions.R
===================================================================
--- pkg/R/extensions.R	                        (rev 0)
+++ pkg/R/extensions.R	2013-07-11 08:05:00 UTC (rev 500)
@@ -0,0 +1,54 @@
+# Copyright 2012 Google Inc. All Rights Reserved.
+# Author: mstokely at google.com (Murray Stokely)
+#
+# This program 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.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+setGeneric( "setExtension", function(object, field, values){
+        standardGeneric( "setExtension" )
+} )
+
+setMethod( "setExtension", "Message", function( object, field, values ){
+	stopifnot(is_extension(field))
+
+	if( is( values, "Message" ) ){
+		values <- list( values )
+	}
+
+        if (is_repeated(field)) {
+            .Call( "setExtensionRepeatedField", object at pointer, field, values,
+                  PACKAGE = "RProtoBuf" )
+        } else {
+            ## this check only makes sense for vector types.
+            stopifnot(length(values) == 1)
+            .Call( "setExtensionField", object at pointer, field, values,
+                  PACKAGE = "RProtoBuf" )
+        }
+	invisible( object )
+} )
+
+
+setGeneric( "getExtension", function(object, field){
+	standardGeneric( "getExtension" )
+} )
+setMethod( "getExtension", "Message", function( object, field){
+	if (is_repeated(field)) {
+		.Call( "getExtensionRepeated", object at pointer, field,
+		      PACKAGE = "RProtoBuf" )
+	} else {
+		.Call( "getExtension", object at pointer, field,
+		      PACKAGE = "RProtoBuf" )
+	}
+} )

Modified: pkg/R/set.R
===================================================================
--- pkg/R/set.R	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/R/set.R	2013-07-11 08:05:00 UTC (rev 500)
@@ -1,3 +1,6 @@
+## TODO(mstokely): Set and fetch are undocumented in Message-class.Rd
+## And untested.  Are they usful?
+
 setGeneric( "set", function(object, field, index, values ){
 	standardGeneric( "set" )
 } )

Modified: pkg/TODO
===================================================================
--- pkg/TODO	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/TODO	2013-07-11 08:05:00 UTC (rev 500)
@@ -1,6 +1,6 @@
 Current TODO list:
 
-1. Extensions [have patch, Kenton didn't like it, it wasn't quite right]
+1. Finish extensions support [enums, messages, nested, more tests]
 2. Unit testing [ongoing]
 3. More as.Message methods [have patch, needs cleanup]
 4. Replace usage of RCPP_FUNCTION_* macros with Rcpp Modules or Attributes.

Added: pkg/inst/unitTests/runit.extensions.R
===================================================================
--- pkg/inst/unitTests/runit.extensions.R	                        (rev 0)
+++ pkg/inst/unitTests/runit.extensions.R	2013-07-11 08:05:00 UTC (rev 500)
@@ -0,0 +1,47 @@
+# Copyright 2013 Google Inc.
+# 
+# This program 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.
+# 
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+test.extension <- function() {
+    if (!exists("protobuf_unittest.TestAllTypes",
+                "RProtoBuf:DescriptorPool")) {
+        unittest.proto.file <- system.file("unitTests", "data",
+                                           "unittest.proto",
+                                           package="RProtoBuf")
+        readProtoFiles(file=unittest.proto.file)
+    }
+
+    checkTrue(inherits(protobuf_unittest.optional_uint32_extension,
+                       "FieldDescriptor"))
+
+    ## Test setting and getting singular extensions.
+    test <- new(protobuf_unittest.TestAllExtensions)
+    test$setExtension(protobuf_unittest.optional_int32_extension,
+                      as.integer(1))
+    checkEquals(test$getExtension(protobuf_unittest.optional_int32_extension),
+                as.integer(1))
+    ## Unset extensions should return NULL.
+    checkEquals(test$getExtension(protobuf_unittest.optional_double_extension),
+                NULL)
+    
+
+    ## Test setting and getting repeated extensions.
+    checkEquals(test$getExtension(protobuf_unittest.repeated_int32_extension),
+                NULL)
+    test$setExtension(protobuf_unittest.repeated_int32_extension, 1:10)
+    checkEquals(test$getExtension(protobuf_unittest.repeated_int32_extension),
+                1:10)
+
+}

Modified: pkg/src/DescriptorPoolLookup.cpp
===================================================================
--- pkg/src/DescriptorPoolLookup.cpp	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/src/DescriptorPoolLookup.cpp	2013-07-11 08:05:00 UTC (rev 500)
@@ -57,8 +57,14 @@
 		    	const GPB::Descriptor* desc = file_desc->message_type( i ) ;
 		    	add( desc->full_name() ); 
 		    	/* should we bother recursing ? */
-		    	/* TODO: also add top level services */
+		    	/* TODO(mstokely): add top level enums and services? */
 		    }
+		    // add top level extensions!
+		    int nexts = file_desc->extension_count() ;
+		    for( int i=0; i<nexts; i++){
+			const GPB::FieldDescriptor* field_desc = file_desc->extension( i ) ;
+			add( field_desc->full_name() );
+		    }
 		}
 		// source_tree.removeDirectories( dirs ) ;
 	}

Added: pkg/src/extensions.cpp
===================================================================
--- pkg/src/extensions.cpp	                        (rev 0)
+++ pkg/src/extensions.cpp	2013-07-11 08:05:00 UTC (rev 500)
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ * Author: Murray Stokely
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "rprotobuf.h"
+#include "fieldtypes.h"
+#include "Rcppsupport.h"
+
+namespace rprotobuf {
+
+// TODO add num_extensions to wrapper_Message.cpp and show this also
+// in show().
+
+
+/**
+ * set a non-repeated extension field to a new value
+ *
+ * @param pointer external pointer to a message
+ * @param sfielddesc S4 field descriptor class
+ * @param value new value for the field
+ *
+ * @return always NULL, the message is modified by reference
+ */
+RcppExport SEXP setExtensionField( SEXP pointer, SEXP sfielddesc, SEXP value ){
+        GPB::Message* message = GET_MESSAGE_POINTER_FROM_XP(pointer) ;
+        const Reflection * ref = message->GetReflection() ;
+        GPB::FieldDescriptor* field_desc = GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(sfielddesc);
+
+	if (!field_desc->is_extension()) {
+		Rprintf("Field is not an extension! tag = %d type = %s\n",
+			field_desc->number(), field_desc->type_name());
+		return R_NilValue;
+	}
+
+	switch (field_desc->type()) {
+		// All floating-point and 64-bit types as R numerics.
+		case TYPE_DOUBLE:
+			ref->SetDouble(message, field_desc, REAL(value)[0]);
+			break;
+		case TYPE_FLOAT:
+			ref->SetFloat(message, field_desc, REAL(value)[0]);
+			break;
+		case TYPE_INT64:
+			ref->SetInt64(message, field_desc, REAL(value)[0]);
+			break;
+		case TYPE_UINT64:
+			ref->SetUInt64(message, field_desc, REAL(value)[0]);
+			break;
+		case TYPE_INT32:
+			ref->SetInt32(message, field_desc, INTEGER(value)[0]);
+			break;
+		case TYPE_UINT32:
+			ref->SetUInt32(message, field_desc, INTEGER(value)[0]);
+			break;
+		case TYPE_BOOL:
+			ref->SetBool(message, field_desc, LOGICAL(value)[0]);
+			break;
+		case TYPE_STRING:
+			ref->SetString(message, field_desc,
+				       CHAR(STRING_ELT(value, 0)));
+			break;
+
+// TODO(mstokely): support enums and messages.
+// Check value is an EnumValueDescriptor first.
+//		case TYPE_ENUM:
+//			ref->SetEnum(message, field_desc, value);
+//			break;
+		default:
+			printf("Not implemented yet");
+	}
+
+	return R_NilValue;
+}
+
+/**
+ * set a repeated extension field to a new value
+ *
+ * @param pointer external pointer to a message
+ * @param sfielddesc S4 field descriptor class
+ * @param value new value for the field
+ *
+ * @return always NULL, the message is modified by reference
+ */
+RcppExport SEXP setExtensionRepeatedField( SEXP pointer,
+					   SEXP sfielddesc, SEXP value ){
+        GPB::Message* message = GET_MESSAGE_POINTER_FROM_XP(pointer) ;
+        const Reflection * ref = message->GetReflection() ;
+        GPB::FieldDescriptor* field_desc = GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(sfielddesc);
+
+	if (!field_desc->is_extension()) {
+		Rprintf("Field is not an extension! tag = %d type = %s\n",
+			field_desc->number(), field_desc->type_name());
+		return R_NilValue;
+	}
+
+	ref->ClearField(message, field_desc);
+	Rprintf("in set repeated extension: length: %d\n", LENGTH(value));
+	switch (field_desc->type()) {		// All floating-point and 64-bit types as R numerics.
+		case TYPE_DOUBLE:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddDouble(message, field_desc,
+					       REAL(value)[i]);
+			}
+			break;
+		case TYPE_FLOAT:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddFloat(message, field_desc,
+						      REAL(value)[i]);
+			}
+			break;
+		case TYPE_INT64:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddInt64(message, field_desc,
+					      REAL(value)[i]);
+			}
+			break;
+		case TYPE_UINT64:
+			for (int i = 0; i < LENGTH(value); i++) {
+				  ref->AddUInt64(message, field_desc,
+						 REAL(value)[i]);
+			}
+			break;
+		case TYPE_INT32:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddInt32(message, field_desc,
+					      INTEGER(value)[i]);
+			}
+			break;
+		case TYPE_UINT32:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddUInt32(message, field_desc,
+					       INTEGER(value)[i]);
+			}
+			break;
+		case TYPE_BOOL:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddBool(message, field_desc,
+					     LOGICAL(value)[i]);
+			}
+			break;
+		case TYPE_STRING:
+			for (int i = 0; i < LENGTH(value); i++) {
+				ref->AddString(message, field_desc,
+					       CHAR(STRING_ELT(value, i)));
+			}
+			break;
+// TODO(mstokely): support enums, messages.
+// Check value is an EnumValueDescriptor first.
+//		case TYPE_ENUM:
+//			ref->SetEnum(message, field_desc, value);
+//			break;
+		default:
+			printf("Not implemented yet");
+	}
+
+	return R_NilValue;
+}
+
+RcppExport SEXP getExtension( SEXP pointer, SEXP sfielddesc){
+        /* grab the Message pointer */
+        const GPB::Message* message = GET_MESSAGE_POINTER_FROM_XP(pointer) ;
+        const Reflection * ref = message->GetReflection() ;
+        GPB::FieldDescriptor* field_desc =
+		GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(sfielddesc);
+
+        if (!field_desc->is_extension()) {
+		Rprintf("Field is not an extension! tag = %d type = %s\n",
+			field_desc->number(), field_desc->type_name());
+		return R_NilValue;
+        }
+	if (!ref->HasField(*message, field_desc)) {
+		return R_NilValue;
+        }
+
+	switch (field_desc->type()) {
+          case TYPE_DOUBLE:
+		return(Rcpp::wrap( ref->GetDouble(*message, field_desc) ));
+          case TYPE_FLOAT:
+		return(Rcpp::wrap( ref->GetFloat(*message, field_desc) ));
+          case TYPE_INT64:
+		return(Rcpp::wrap( ref->GetInt64(*message, field_desc) ));
+          case TYPE_UINT64:
+		return(Rcpp::wrap( ref->GetUInt64(*message, field_desc) ));
+          case TYPE_INT32:
+		return(Rcpp::wrap( ref->GetInt32(*message, field_desc) ));
+          case TYPE_UINT32:
+		return(Rcpp::wrap( ref->GetUInt32(*message, field_desc) ));
+          case TYPE_BOOL:
+		return(Rcpp::wrap( ref->GetBool(*message, field_desc) ));
+          case TYPE_STRING:
+		return(Rcpp::wrap( ref->GetString(*message, field_desc) ));
+          default:
+		printf("Not implemented yet");
+        }
+        return R_NilValue;
+}
+
+RcppExport SEXP getExtensionRepeated( SEXP pointer, SEXP sfielddesc){
+        /* grab the Message pointer */
+        const GPB::Message* message = GET_MESSAGE_POINTER_FROM_XP(pointer) ;
+        const Reflection * ref = message->GetReflection() ;
+        GPB::FieldDescriptor* field_desc =
+		GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(sfielddesc);
+
+        if (!field_desc->is_extension()) {
+		Rprintf("Field is not an extension! tag = %d type = %s\n",
+			field_desc->number(), field_desc->type_name());
+		return R_NilValue;
+        }
+	if (ref->FieldSize(*message, field_desc) < 1) {
+		return R_NilValue;
+        }
+
+    	switch( GPB::FieldDescriptor::TypeToCppType(field_desc->type()) ){
+	  case CPPTYPE_DOUBLE:
+			return Rcpp::wrap( RepeatedFieldImporter<double>(ref,
+								 *message,
+								 field_desc));
+	  case CPPTYPE_FLOAT:
+			return Rcpp::wrap( RepeatedFieldImporter<float>(ref,
+								 *message,
+								 field_desc));
+  	  case CPPTYPE_INT32:
+		return Rcpp::wrap( RepeatedFieldImporter<int32>(ref,
+								*message,
+								field_desc));
+	  case CPPTYPE_UINT32:
+		return Rcpp::wrap( RepeatedFieldImporter<uint32>(ref,
+								*message,
+								field_desc));
+	  case CPPTYPE_INT64:
+		return Rcpp::wrap( RepeatedFieldImporter<int64>(ref,
+								*message,
+								field_desc));
+	  case CPPTYPE_UINT64:
+		return Rcpp::wrap( RepeatedFieldImporter<uint64>(ref,
+								*message,
+								field_desc));
+	  case CPPTYPE_BOOL:
+		return Rcpp::wrap( RepeatedFieldImporter<bool>(ref,
+							       *message,
+							       field_desc));
+          default:
+		printf("Not implemented yet");
+        }
+        return R_NilValue;
+}
+
+}  // namespace rprotobuf

Modified: pkg/src/lookup.cpp
===================================================================
--- pkg/src/lookup.cpp	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/src/lookup.cpp	2013-07-11 08:05:00 UTC (rev 500)
@@ -37,13 +37,21 @@
  } else {
  	/* try the generated pool */
  	const GPB::DescriptorPool*  pool = GPB::DescriptorPool::generated_pool() ;
- 	if( pool->FindMessageTypeByName( name ) ||  pool->FindEnumTypeByName( name ) || pool->FindServiceByName( name ) || pool->FindMethodByName( name ) ){
- 		DescriptorPoolLookup::add( name ) ;
- 		val = _TRUE_ ;
- 	} else {
- 		/* try the runtime pool */
- 		pool = DescriptorPoolLookup::pool() ;
- 		if( pool->FindMessageTypeByName( name ) ||  pool->FindEnumTypeByName( name ) || pool->FindServiceByName( name ) || pool->FindMethodByName( name ) ){
+	if( pool->FindMessageTypeByName( name ) ||
+	    pool->FindEnumTypeByName( name ) ||
+	    pool->FindServiceByName( name ) ||
+	    pool->FindMethodByName( name ) ||
+	    pool->FindExtensionByName( name )){
+		DescriptorPoolLookup::add( name ) ;
+		val = _TRUE_ ;
+	} else {
+		/* try the runtime pool */
+		pool = DescriptorPoolLookup::pool() ;
+		if( pool->FindMessageTypeByName( name ) ||
+		    pool->FindEnumTypeByName( name ) ||
+		    pool->FindServiceByName( name ) ||
+		    pool->FindMethodByName( name ) ||
+		    pool->FindExtensionByName( name )){
  			DescriptorPoolLookup::add( name ) ;
  			val = _TRUE_ ;
  		}
@@ -67,20 +75,28 @@
  		 	/* enum */
  		 	DescriptorPoolLookup::add( name_string ) ;
  		 	return S4_EnumDescriptor( enum_desc ); 
+
  		 } else{
-			const GPB::ServiceDescriptor* service_desc = pool->FindServiceByName( name_string ) ;
-			if( service_desc ){
+			const GPB::FieldDescriptor* extension_desc =
+				pool->FindExtensionByName( name_string ) ;
+			if( extension_desc ){
+				/* extension */
 				DescriptorPoolLookup::add( name_string ) ;
-				return S4_ServiceDescriptor( service_desc ) ;
- 		 	} else {
- 		 		const GPB::MethodDescriptor* method_desc = pool->FindMethodByName( name_string ); 
- 		 		if( method_desc ){
+				return S4_FieldDescriptor( extension_desc ) ;
+                        } else{
+				const GPB::ServiceDescriptor* service_desc = pool->FindServiceByName( name_string ) ;
+				if( service_desc ){
 					DescriptorPoolLookup::add( name_string ) ;
-					return S4_MethodDescriptor( method_desc ); 
- 		 		}
- 		 	}
- 		 }
- 		
+					return S4_ServiceDescriptor( service_desc ) ;
+	 		 	} else {
+			 		const GPB::MethodDescriptor* method_desc = pool->FindMethodByName( name_string ); 
+			 		if( method_desc ){
+						DescriptorPoolLookup::add( name_string ) ;
+						return S4_MethodDescriptor( method_desc ); 
+			 		}
+				}
+			}
+		 }
  	}
  	return R_NilValue ;
 }

Modified: pkg/src/rprotobuf.h
===================================================================
--- pkg/src/rprotobuf.h	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/src/rprotobuf.h	2013-07-11 08:05:00 UTC (rev 500)
@@ -91,6 +91,9 @@
 #define GET_DESCRIPTOR_POINTER_FROM_XP(xp)  (GPB::Descriptor*) EXTPTR_PTR( xp )
 #define GET_DESCRIPTOR_POINTER_FROM_S4(m)   (GPB::Descriptor*) EXTPTR_PTR( GET_SLOT( m, Rf_install("pointer") ) )
 
+#define GET_FIELD_DESCRIPTOR_POINTER_FROM_XP(xp)  (GPB::FieldDescriptor*) EXTPTR_PTR( xp )
+#define GET_FIELD_DESCRIPTOR_POINTER_FROM_S4(m)   (GPB::FieldDescriptor*) EXTPTR_PTR( GET_SLOT( m, Rf_install("pointer") ) )
+
 #define GET_METHOD(xp)  (GPB::MethodDescriptor*) EXTPTR_PTR( xp )
 
 #define COPYSTRING(s) s

Modified: pkg/src/wrapper_FileDescriptor.cpp
===================================================================
--- pkg/src/wrapper_FileDescriptor.cpp	2013-07-11 00:47:27 UTC (rev 499)
+++ pkg/src/wrapper_FileDescriptor.cpp	2013-07-11 08:05:00 UTC (rev 500)
@@ -18,8 +18,9 @@
 	int ntypes  = desc->message_type_count() ;
 	int nenums  = desc->enum_type_count() ;
 	int nserv   = desc->service_count() ;
+	int nexts   = desc->extension_count() ;
 	
-	Rcpp::CharacterVector res( ntypes + nenums + nserv ) ;
+	Rcpp::CharacterVector res( ntypes + nenums + nserv + nexts ) ;
 	int i=0;
 	int j=0; 
 	while( i<ntypes){
@@ -39,6 +40,12 @@
 		i++; 
 		j++;
 	}
+	i = 0; 
+	while( i<nexts){
+		res[j] = desc->extension(i)->name() ;
+		i++;
+		j++;
+	}
 	return res ;
 	
 }
@@ -51,7 +58,8 @@
 	int ntypes    = desc->message_type_count() ;
 	int nenums    = desc->enum_type_count() ;
 	int nserv     = desc->service_count() ;
-	int n = ntypes + nenums + nserv ;
+	int nexts     = desc->extension_count() ;
+	int n = ntypes + nenums + nserv + nexts;
 	
 	Rcpp::CharacterVector names(n) ; 
 	Rcpp::List res( n ); 
@@ -69,6 +77,11 @@
 		res[j] = S4_ServiceDescriptor( desc->service(i) );
 		names[j] = desc->service(i)->name() ;
 	}
+	for( i=0; i<nexts; j++, i++){
+		res[j] = S4_FieldDescriptor( desc->extension(i) );
+		// always use full names for extensions
+		names[j] = desc->extension(i)->full_name() ;
+	}
 	res.names() = names ;
 	return res; 
 }



More information about the Rprotobuf-commits mailing list