Ejemplo n.º 1
0
/**
 * 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 ) ;
}
Ejemplo n.º 2
0
/**
 * 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
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
                    }
                }
            }
        }
    }
}