[Rprotobuf-commits] r395 - in pkg: . inst inst/unitTests inst/unitTests/data src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Oct 13 21:39:57 CEST 2010
Author: edd
Date: 2010-10-13 21:39:57 +0200 (Wed, 13 Oct 2010)
New Revision: 395
Added:
pkg/inst/unitTests/data/bytes.proto
pkg/inst/unitTests/runit.bytes.R
Modified:
pkg/NEWS
pkg/inst/ChangeLog
pkg/src/extractors.cpp
pkg/src/mutators.cpp
pkg/src/rprotobuf.h
pkg/src/wrapper_Message.cpp
Log:
applied patch kindly submitted by Koert
added his unit test and support file too
Modified: pkg/NEWS
===================================================================
--- pkg/NEWS 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/NEWS 2010-10-13 19:39:57 UTC (rev 395)
@@ -1,3 +1,7 @@
+0.2.1 TBD
+
+ o Support for raw bytes added thanks to a patch by Koert Kuipers
+
0.2.0 2010-09-10
o Second release with numerous internal changes made possible by
Modified: pkg/inst/ChangeLog
===================================================================
--- pkg/inst/ChangeLog 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/inst/ChangeLog 2010-10-13 19:39:57 UTC (rev 395)
@@ -1,3 +1,8 @@
+2010-10-13 Dirk Eddelbuettel <edd at debian.org>
+
+ * src/*: applied patch by Koert Kuipers to support raw bytes
+ * inst/unitTests/runit.bytes.R: also added unit test by Koert
+
2010-09-11 Dirk Eddelbuettel <edd at debian.org>
* DESCRIPTION: Release 0.2.0
Added: pkg/inst/unitTests/data/bytes.proto
===================================================================
--- pkg/inst/unitTests/data/bytes.proto (rev 0)
+++ pkg/inst/unitTests/data/bytes.proto 2010-10-13 19:39:57 UTC (rev 395)
@@ -0,0 +1,8 @@
+option optimize_for = SPEED;
+option java_outer_classname = "BytesProto";
+
+message TestBytes {
+ required bytes req = 1;
+ optional bytes opt = 2 [default = "hello world"];
+ repeated bytes rep = 3;
+}
Added: pkg/inst/unitTests/runit.bytes.R
===================================================================
--- pkg/inst/unitTests/runit.bytes.R (rev 0)
+++ pkg/inst/unitTests/runit.bytes.R 2010-10-13 19:39:57 UTC (rev 395)
@@ -0,0 +1,21 @@
+
+.setUp <- function(){
+ if( ! exists( "TestBytes", "RProtoBuf:DescriptorPool" ) ){
+ unitest.proto.file <- system.file( "unitTests", "data", "bytes.proto", package = "RProtoBuf" )
+ readProtoFiles(file = unitest.proto.file)
+ }
+}
+
+test.all <- function() {
+ test <- new(TestBytes, req = "abc", rep = list(charToRaw("def"), raw(10)))
+ checkEquals(rawToChar(test$req), "abc")
+ checkEquals(rawToChar(test$opt), "hello world")
+ checkEquals(test$rep, list(charToRaw("def"), raw(10)))
+ test$rep[[3]]=charToRaw("ghi")
+ checkEquals(test$rep, list(charToRaw("def"), raw(10), charToRaw("ghi")))
+ ser <- serialize(test, NULL)
+ test1 <- read(TestBytes, ser)
+ checkEquals(rawToChar(test1$req), "abc")
+ checkEquals(rawToChar(test1$opt), "hello world")
+ checkEquals(test1$rep, list(charToRaw("def"), raw(10), charToRaw("ghi")))
+}
Property changes on: pkg/inst/unitTests/runit.bytes.R
___________________________________________________________________
Added: svn:executable
+ *
Modified: pkg/src/extractors.cpp
===================================================================
--- pkg/src/extractors.cpp 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/src/extractors.cpp 2010-10-13 19:39:57 UTC (rev 395)
@@ -51,7 +51,7 @@
case TYPE : \
return Rcpp::wrap( RepeatedFieldImporter<DATATYPE>(ref, *message, fieldDesc) ) ; \
- HANDLE_REPEATED_FIELD(CPPTYPE_INT32, GPB::int32) ;
+ HANDLE_REPEATED_FIELD(CPPTYPE_INT32, GPB::int32) ;
HANDLE_REPEATED_FIELD(CPPTYPE_INT64, GPB::int64) ;
HANDLE_REPEATED_FIELD(CPPTYPE_UINT32 , GPB::uint32) ;
HANDLE_REPEATED_FIELD(CPPTYPE_UINT64 , GPB::uint64) ;
@@ -59,10 +59,24 @@
HANDLE_REPEATED_FIELD(CPPTYPE_FLOAT, float) ;
HANDLE_REPEATED_FIELD(CPPTYPE_BOOL, bool) ;
HANDLE_REPEATED_FIELD(CPPTYPE_ENUM, enum_field ) ;
- HANDLE_REPEATED_FIELD(CPPTYPE_STRING, std::string ) ;
HANDLE_REPEATED_FIELD(CPPTYPE_MESSAGE, message_field ) ;
#undef HANDLE_REPEATED_FIELD
+ case CPPTYPE_STRING:
+ if (fieldDesc->type() == TYPE_STRING) {
+ return Rcpp::wrap( RepeatedFieldImporter<std::string>(ref, *message, fieldDesc) ) ;
+ } else if (fieldDesc->type() == TYPE_BYTES) {
+ int field_size = ref->FieldSize( *message, fieldDesc ) ;
+ Rcpp::List res(field_size);
+ for (int i=0; i<field_size; i++) {
+ std::string s = ref->GetRepeatedString(*message, fieldDesc, i);
+ res[i] = Rcpp::wrap(std::vector<Rbyte>(s.begin(), s.end()));
+ }
+ return res;
+ } else {
+ throwException( "unknown field type with CPP_TYPE STRING", "ConversionException" ) ;
+ }
+
}
} else {
@@ -81,14 +95,22 @@
HANDLE_SINGLE_FIELD( CPPTYPE_DOUBLE, Double );
HANDLE_SINGLE_FIELD( CPPTYPE_FLOAT, Float );
HANDLE_SINGLE_FIELD( CPPTYPE_BOOL, Bool );
- HANDLE_SINGLE_FIELD( CPPTYPE_STRING, String );
#undef HANDLE_SINGLE_FIELD
+ case CPPTYPE_STRING:
+ if (fieldDesc->type() == TYPE_STRING) {
+ return Rcpp::wrap( ref->GetString(*message, fieldDesc) );
+ } else if (fieldDesc->type() == TYPE_BYTES) {
+ std::string s = ref->GetString(*message, fieldDesc);
+ return Rcpp::wrap(std::vector<Rbyte>(s.begin(), s.end()));
+ } else {
+ throwException( "unknown field type with CPP_TYPE STRING", "ConversionException" ) ;
+ }
case CPPTYPE_ENUM :
- return Rcpp::wrap( ref->GetEnum( *message, fieldDesc )->number() ) ;
+ return Rcpp::wrap( ref->GetEnum( *message, fieldDesc )->number() ) ;
- case CPPTYPE_MESSAGE:
- return S4_Message( CLONE( &ref->GetMessage( *message, fieldDesc ) ) ) ;
+ case CPPTYPE_MESSAGE:
+ return S4_Message( CLONE( &ref->GetMessage( *message, fieldDesc ) ) ) ;
break ;
}
}
Modified: pkg/src/mutators.cpp
===================================================================
--- pkg/src/mutators.cpp 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/src/mutators.cpp 2010-10-13 19:39:57 UTC (rev 395)
@@ -152,18 +152,24 @@
return "" ; // -Wall, should not happen since we only call this when we know it works
}
-/**
- * calls the R function charToRaw to convert raw into a string
- *
- * @param raw raw vector
- * @return a string (STRSXP)
- */
-/* FIXME: maybe we don't need to go back to R for this */
-SEXP rawToString( SEXP raw){
- SEXP call = PROTECT( Rf_lang2( Rf_install("charToRaw"), raw ) ) ;
- SEXP res = PROTECT( Rf_eval( call, R_GlobalEnv ) );
- UNPROTECT( 2 ) ; /* res, call */
- return res ;
+std::string GET_bytes( SEXP x, int index ){
+ switch( TYPEOF(x)) {
+ case RAWSXP:
+ if (index == 0) {
+ return(std::string((const char *) RAW(x), (size_t) LENGTH(x)));
+ } else {
+ throwException( "cannot cast SEXP to bytes", "CastException" ) ;
+ }
+ case VECSXP:
+ if (TYPEOF(VECTOR_ELT(x, index)) == RAWSXP) {
+ return(std::string((const char *) RAW(VECTOR_ELT(x, index)), (size_t) LENGTH(VECTOR_ELT(x, index))));
+ } else {
+ throwException( "cannot cast SEXP to bytes", "CastException" ) ;
+ }
+ default:
+ throwException( "cannot cast SEXP to bytes", "CastException" ) ;
+ }
+ return "" ; // -Wall, should not happen since we only call this when we know it works
}
/**
@@ -189,6 +195,25 @@
return _TRUE_ ;
}
+/**
+ * indicates if this is a list of raws
+ *
+ * @param x a list (VECSXP)
+ * @return TRUE if all objects are instances of RAWSXP
+ */
+Rboolean allAreRaws( SEXP x) {
+
+ if( TYPEOF(x) != VECSXP ) return _FALSE_ ;
+
+ int n = LENGTH(x) ;
+ SEXP current ;
+ for( int i=0; i<n; i++){
+ current = VECTOR_ELT( x, i) ;
+ /* not a RAWSXP */
+ if( TYPEOF(current) != RAWSXP ) return _FALSE_ ;
+ }
+ return _TRUE_ ;
+}
/**
* check that all the values contained in value are suitable for the
@@ -345,7 +370,9 @@
value_size = 1 ; /* we will store the message payload */
} else if( TYPEOF(value) == VECSXP && allAreMessages( value ) ){
value_size = LENGTH(value) ;
- } else{
+ } else if( TYPEOF(value) == VECSXP && allAreRaws( value ) ){
+ value_size = LENGTH(value) ;
+ } else {
throwException( "cannot convert to string", "ConversionException" ) ;
}
}
@@ -744,8 +771,20 @@
}
case RAWSXP:
{
- ref->SetRepeatedString( message, field_desc, 0, COPYSTRING( CHAR(STRING_ELT(rawToString(value),0 )) ) ) ;
- }
+ /* in any case, fill the values up to field_size */
+ int i = 0;
+ for ( ; i<field_size; i++) {
+ ref->SetRepeatedString( message, field_desc, i, GET_bytes(value, 0)) ;
+ }
+
+ /* then add some if needed */
+ if( value_size > field_size ){
+ for( ; i<value_size; i++) {
+ ref->AddString( message, field_desc, GET_bytes(value, 0)) ;
+ }
+ }
+ break;
+ }
case S4SXP:
{
/* check if value is a message */
@@ -759,28 +798,43 @@
}
case VECSXP:
{
- // we know it is a list of messages because it
+ // we know it is a list of messages or raws because it
// has been tested above
-
- // FIXME: we should probably use SerializeToString
- // as indicated in the protobuf api documentation
- // http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message_lite.html#MessageLite.SerializeAsString.details
- GPB::Message* __mess ;
-
- /* in any case, fill the values up to field_size */
- int i = 0;
- for( ; i<field_size; i++){
- __mess = GET_MESSAGE_POINTER_FROM_S4( VECTOR_ELT( value, i ) );
- ref->SetRepeatedString( message, field_desc, i, __mess->SerializeAsString() ) ;
- }
-
- /* then add some if needed */
- if( value_size > field_size ){
- for( ; i<value_size; i++){
- __mess = GET_MESSAGE_POINTER_FROM_S4( VECTOR_ELT( value, i ) );
- ref->AddString( message, field_desc, __mess->SerializeAsString() ) ;
- }
- }
+ if (LENGTH(value) > 0 && TYPEOF(VECTOR_ELT(value, 0)) == RAWSXP ) {
+ /* in any case, fill the values up to field_size */
+ int i = 0;
+ for( ; i<field_size; i++) {
+ ref->SetRepeatedString( message, field_desc, i, GET_bytes(value,i )) ;
+ }
+
+ /* then add some if needed */
+ if( value_size > field_size ) {
+ for( ; i<value_size; i++){
+ ref->AddString( message, field_desc, GET_bytes(value,i )) ;
+ }
+ }
+ } else {
+ // FIXME: we should probably use SerializeToString
+ // as indicated in the protobuf api documentation
+ // http://code.google.com/apis/protocolbuffers/docs/reference/cpp/google.protobuf.message_lite.html#MessageLite.SerializeAsString.details
+ GPB::Message* __mess ;
+
+ /* in any case, fill the values up to field_size */
+ int i = 0;
+ for( ; i<field_size; i++){
+ __mess = GET_MESSAGE_POINTER_FROM_S4( VECTOR_ELT( value, i ) );
+ ref->SetRepeatedString( message, field_desc, i, __mess->SerializeAsString() ) ;
+ }
+
+ /* then add some if needed */
+ if( value_size > field_size ){
+ for( ; i<value_size; i++){
+ __mess = GET_MESSAGE_POINTER_FROM_S4( VECTOR_ELT( value, i ) );
+ ref->AddString( message, field_desc, __mess->SerializeAsString() ) ;
+ }
+ }
+
+ }
break ;
}
@@ -936,7 +990,7 @@
}
case RAWSXP:
{
- ref->SetString(message, field_desc, COPYSTRING( CHAR(STRING_ELT( rawToString( value ) ,0 )) ) ) ;
+ ref->SetString(message, field_desc, GET_bytes(value, 0)) ;
break ;
}
case S4SXP:
Modified: pkg/src/rprotobuf.h
===================================================================
--- pkg/src/rprotobuf.h 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/src/rprotobuf.h 2010-10-13 19:39:57 UTC (rev 395)
@@ -59,7 +59,7 @@
/* uncomment for debugging */
-// #define RPB_DEBUG
+#define RPB_DEBUG
#ifdef RPB_DEBUG
#define RPB_DEBUG_BEGIN(__WHAT__) Rprintf( "<" #__WHAT__ ">\n" ) ;
@@ -138,6 +138,7 @@
RcppExport uint64 GET_uint64( SEXP, int ) ;
RcppExport bool GET_bool( SEXP, int) ;
RcppExport std::string GET_stdstring( SEXP, int ) ;
+RcppExport std::string GET_bytes( SEXP, int ) ;
RcppExport void CHECK_values_for_enum( GPB::FieldDescriptor*, SEXP) ;
RcppExport void CHECK_messages( GPB::FieldDescriptor*, SEXP) ;
Modified: pkg/src/wrapper_Message.cpp
===================================================================
--- pkg/src/wrapper_Message.cpp 2010-10-13 19:25:26 UTC (rev 394)
+++ pkg/src/wrapper_Message.cpp 2010-10-13 19:39:57 UTC (rev 395)
@@ -840,7 +840,6 @@
// {{{ string
case TYPE_STRING:
- case TYPE_BYTES:
{
if( TYPEOF(values) == STRSXP ){
for( int i=0 ; i<value_size; i++){
@@ -852,6 +851,22 @@
break ;
}
// }}}
+
+ // {{{ bytes
+ case TYPE_BYTES:
+ {
+ if( TYPEOF(values) == RAWSXP ){
+ ref->AddString( message, field_desc, GET_bytes(values,0 )) ;
+ } else if( TYPEOF(values) == VECSXP ){
+ for( int i=0 ; i<value_size; i++) {
+ ref->AddString( message, field_desc, GET_bytes(values,i )) ;
+ }
+ } else{
+ throwException( "Cannot convert to bytes", "ConversionException" ) ;
+ }
+ break ;
+ }
+ // }}}
// {{{ message
case TYPE_MESSAGE:
@@ -983,7 +998,6 @@
return res;
}
case TYPE_STRING:
- case TYPE_BYTES:
{
const GPB::Reflection* ref = message->GetReflection() ;
Rcpp::CharacterVector res(n) ;
@@ -992,6 +1006,16 @@
}
return res ;
}
+ case TYPE_BYTES:
+ {
+ const GPB::Reflection* ref = message->GetReflection() ;
+ Rcpp::List res(n) ;
+ for( int i=0; i<n; i++){
+ std::string s = ref->GetRepeatedString( *message, field_desc, index[i] );
+ res[i] = std::vector<Rbyte>(s.begin(), s.end());
+ }
+ return res ;
+ }
case TYPE_MESSAGE:
case TYPE_GROUP:
{
@@ -1101,7 +1125,6 @@
break ;
}
case TYPE_STRING:
- case TYPE_BYTES:
{
for( int i=0; i<n; i++){
@@ -1111,6 +1134,16 @@
}
break ;
}
+ case TYPE_BYTES:
+ {
+
+ for( int i=0; i<n; i++){
+ ref->SetRepeatedString( message, field_desc,
+ index[i],
+ GET_bytes( values, i ) ) ;
+ }
+ break ;
+ }
case TYPE_ENUM :
{
CHECK_values_for_enum( field_desc, values ) ;
More information about the Rprotobuf-commits
mailing list