/** * Add descriptors from a proto file to the descriptor pool. * * Specifically, message types, extensions, and enums are added. * Services are not added because they are not really used in RProtoBuf. * * @param files A character vector of .proto files to import. * @param dirs A character vector of directories to import from. * @throws Rcpp::exception if a file can't be loaded (uncaught). */ void DescriptorPoolLookup::importProtoFiles(SEXP files, SEXP dirs) { source_tree.addDirectories(dirs); int n = LENGTH(files); for (int j = 0; j < n; j++) { const GPB::FileDescriptor* file_desc = importer.Import(CHAR(STRING_ELT(files, j))); if (!file_desc) { std::string message = std::string("Could not load proto file '") + CHAR(STRING_ELT(files, j)) + "'\n"; Rcpp_error(message.c_str()); } // add top level messages from the file. int ntypes = file_desc->message_type_count(); for (int i = 0; i < ntypes; i++) { const GPB::Descriptor* desc = file_desc->message_type(i); add(desc->full_name()); /* should we bother recursing ? */ } // 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()); } // add top level enums. int nenums = file_desc->enum_type_count(); for (int i = 0; i < nenums; i++) { const GPB::EnumDescriptor* enum_desc = file_desc->enum_type(i); add(enum_desc->full_name()); } } // source_tree.removeDirectories( dirs ) ; }
/** * Fetch a subset of the values of a field. * * @param (GPB::Message*) external pointer * @param field name or tag number of the field * @param index */ RPB_FUNCTION_3(SEXP, METHOD(get_field_values), Rcpp::XPtr<GPB::Message> message, SEXP field, Rcpp::IntegerVector index) { GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); if (!field_desc->is_repeated()) { Rcpp_error("fetch can only be used on repeated fields"); } int n = index.size(); switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: case TYPE_UINT32: case TYPE_FIXED32: case TYPE_UINT64: case TYPE_FIXED64: case TYPE_ENUM: { Rcpp::IntegerVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_INT(message, field_desc, index[i]); } return res; } case TYPE_DOUBLE: case TYPE_FLOAT: { Rcpp::NumericVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_DOUBLE(message, field_desc, index[i]); } return res; } case TYPE_BOOL: { Rcpp::LogicalVector res(n); for (int i = 0; i < n; i++) { res[i] = MESSAGE_GET_REPEATED_DOUBLE(message, field_desc, index[i]); } return res; } case TYPE_STRING: { const GPB::Reflection* ref = message->GetReflection(); Rcpp::CharacterVector res(n); for (int i = 0; i < n; i++) { res[i] = ref->GetRepeatedString(*message, field_desc, index[i]); } 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: { const GPB::Reflection* ref = message->GetReflection(); Rcpp::List res(n); for (int i = 0; i < n; i++) { res[i] = S4_Message(CLONE(&ref->GetRepeatedMessage(*message, field_desc, i))); } return res; } default: throw std::range_error("unknown type"); } return R_NilValue; // Unreachable. For -Wall }
bool identical_messages_(const GPB::Message* m1, const GPB::Message* m2, double tol) { const GPB::Descriptor* d1 = m1->GetDescriptor(); const GPB::Descriptor* d2 = m2->GetDescriptor(); /* first of all, check if this is the same message type */ if (d1 != d2) { return false; } const GPB::Reflection* ref = m2->GetReflection(); /* iterate field descriptors */ int nf = d1->field_count(); for (int i = 0; i < nf; i++) { const GPB::FieldDescriptor* field_desc = d1->field(i); if (field_desc->is_repeated()) { /* test if the size differs */ int fs = ref->FieldSize(*m1, field_desc); if (fs != ref->FieldSize(*m2, field_desc)) return false; /* test all items */ switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedInt32(*m1, field_desc, j) != ref->GetRepeatedInt32(*m2, field_desc, j)) return false; } break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedInt64(*m1, field_desc, j) != ref->GetRepeatedInt64(*m2, field_desc, j)) return false; } break; } case TYPE_UINT32: case TYPE_FIXED32: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedUInt32(*m1, field_desc, j) != ref->GetRepeatedUInt32(*m2, field_desc, j)) return false; } break; } case TYPE_UINT64: case TYPE_FIXED64: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedUInt64(*m1, field_desc, j) != ref->GetRepeatedUInt64(*m2, field_desc, j)) return false; } break; } case TYPE_DOUBLE: { for (int j = 0; j < fs; j++) { if (!SAME(ref->GetRepeatedDouble(*m1, field_desc, j), ref->GetRepeatedDouble(*m2, field_desc, j), tol)) return false; } break; } case TYPE_FLOAT: { for (int j = 0; j < fs; j++) { if (!SAME(ref->GetRepeatedFloat(*m1, field_desc, j), ref->GetRepeatedFloat(*m2, field_desc, j), tol)) return false; } break; } case TYPE_BOOL: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedBool(*m1, field_desc, j) != ref->GetRepeatedBool(*m2, field_desc, j)) return false; } break; } case TYPE_STRING: case TYPE_BYTES: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedString(*m1, field_desc, j) != ref->GetRepeatedString(*m2, field_desc, j)) return false; } break; } case TYPE_ENUM: { for (int j = 0; j < fs; j++) { if (ref->GetRepeatedEnum(*m1, field_desc, j) != ref->GetRepeatedEnum(*m2, field_desc, j)) return false; } break; } case TYPE_MESSAGE: case TYPE_GROUP: { for (int j = 0; j < fs; j++) { const GPB::Message* mm1 = &ref->GetRepeatedMessage(*m1, field_desc, j); const GPB::Message* mm2 = &ref->GetRepeatedMessage(*m2, field_desc, j); if (!identical_messages_(mm1, mm2, tol)) { return false; } } break; } default: Rcpp_error("unknown type"); } } else { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { if (ref->GetInt32(*m1, field_desc) != ref->GetInt32(*m2, field_desc)) return false; break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { if (ref->GetInt64(*m1, field_desc) != ref->GetInt64(*m2, field_desc)) return false; break; } case TYPE_UINT32: case TYPE_FIXED32: { if (ref->GetUInt32(*m1, field_desc) != ref->GetUInt32(*m2, field_desc)) return false; break; } case TYPE_UINT64: case TYPE_FIXED64: { if (ref->GetUInt64(*m1, field_desc) != ref->GetUInt64(*m2, field_desc)) return false; break; } case TYPE_DOUBLE: { if (ref->GetDouble(*m1, field_desc) != ref->GetDouble(*m2, field_desc)) return false; break; } case TYPE_FLOAT: { if (ref->GetFloat(*m1, field_desc) != ref->GetFloat(*m2, field_desc)) return false; break; } case TYPE_BOOL: { if (ref->GetBool(*m1, field_desc) != ref->GetBool(*m2, field_desc)) return false; break; } case TYPE_STRING: case TYPE_BYTES: { if (ref->GetString(*m1, field_desc) != ref->GetString(*m2, field_desc)) return false; break; } case TYPE_ENUM: { if (ref->GetEnum(*m1, field_desc) != ref->GetEnum(*m2, field_desc)) return false; break; } case TYPE_MESSAGE: case TYPE_GROUP: { const GPB::Message* mm1 = &ref->GetMessage(*m1, field_desc); const GPB::Message* mm2 = &ref->GetMessage(*m2, field_desc); if (!identical_messages_(mm1, mm2, tol)) { return false; } break; } default: Rcpp_error("unknown type"); } } } /* finally */ return true; }
RPB_FUNCTION_VOID_3(METHOD(set_field_size), Rcpp::XPtr<GPB::Message> message, SEXP field, int target) { const GPB::FieldDescriptor* field_desc = getFieldDescriptor(message, field); const GPB::Reflection* ref = message->GetReflection(); if (field_desc->is_repeated()) { int current = ref->FieldSize(*message, field_desc); if (target == 0) { ref->ClearField(message, field_desc); } else if (current > target) { while (current != target) { ref->RemoveLast(message, field_desc); current--; } } else if (current == target) { /* nothing to do */ } else {/* current < target */ while (current != target) { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { ref->AddInt32(message, field_desc, (int32)0); break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { ref->AddInt64(message, field_desc, (int64)0); break; } case TYPE_UINT32: case TYPE_FIXED32: { ref->AddUInt32(message, field_desc, (uint32)0); break; } case TYPE_UINT64: case TYPE_FIXED64: { ref->AddUInt32(message, field_desc, (uint64)0); break; } case TYPE_DOUBLE: { ref->AddDouble(message, field_desc, (double)0.0); break; } case TYPE_FLOAT: { ref->AddFloat(message, field_desc, (float)0.0); break; } case TYPE_BOOL: { ref->AddBool(message, field_desc, (bool)0); break; } case TYPE_STRING: case TYPE_BYTES: { ref->AddString(message, field_desc, ""); break; } case TYPE_MESSAGE: case TYPE_GROUP: { /* fill with the prototype for that message type */ Rcpp_error("growing repeated messages not implemented, patches welcome"); break; } case TYPE_ENUM: { /* fill with the prototype for that message type */ Rcpp_error("growing repeated enums not implemented yet, patches welcome"); break; } } /* switch */ current++; } /* while */ } } else { if (target == 0) { if (ref->HasField(*message, field_desc)) { ref->ClearField(message, field_desc); } } else { if (!ref->HasField(*message, field_desc)) { switch (field_desc->type()) { case TYPE_INT32: case TYPE_SINT32: case TYPE_SFIXED32: { ref->SetInt32(message, field_desc, (int32)0); break; } case TYPE_INT64: case TYPE_SINT64: case TYPE_SFIXED64: { ref->SetInt64(message, field_desc, (int64)0); break; } case TYPE_UINT32: case TYPE_FIXED32: { ref->SetUInt32(message, field_desc, (uint32)0); break; } case TYPE_UINT64: case TYPE_FIXED64: { ref->SetUInt32(message, field_desc, (uint64)0); break; } case TYPE_DOUBLE: { ref->SetDouble(message, field_desc, (double)0.0); break; } case TYPE_FLOAT: { ref->SetFloat(message, field_desc, (float)0.0); break; } case TYPE_BOOL: { ref->SetBool(message, field_desc, (bool)0); break; } case TYPE_STRING: case TYPE_BYTES: { ref->SetString(message, field_desc, ""); break; } case TYPE_MESSAGE: case TYPE_GROUP: { /* fill with the prototype for that message type */ Rcpp_error("not implemented yet, patches welcome"); break; } case TYPE_ENUM: { /* fill with the prototype for that message type */ Rcpp_error("not implemented yet, patches welcome"); break; } } } } } }