diff --git a/descriptor/descriptor.h b/descriptor/descriptor.h index 1e7e927502..e8765f2c88 100644 --- a/descriptor/descriptor.h +++ b/descriptor/descriptor.h @@ -3,7 +3,8 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H_ #define GOOGLE_PROTOBUF_DESCRIPTOR_H_ -#include "upb_msg.h" +#include "upb_string.h" +#include "upb_array.h" /* Enums. */ @@ -25,23 +26,23 @@ typedef enum google_protobuf_FieldDescriptorProto_Type { GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64 = 16, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18 } google_protobuf_FieldDescriptorProto_Type; typedef enum google_protobuf_FieldDescriptorProto_Label { GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED = 3 } google_protobuf_FieldDescriptorProto_Label; typedef enum google_protobuf_FileOptions_OptimizeMode { GOOGLE_PROTOBUF_FILEOPTIONS_SPEED = 1, - GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2, + GOOGLE_PROTOBUF_FILEOPTIONS_CODE_SIZE = 2 } google_protobuf_FileOptions_OptimizeMode; typedef enum google_protobuf_FieldOptions_CType { GOOGLE_PROTOBUF_FIELDOPTIONS_CORD = 1, - GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2, + GOOGLE_PROTOBUF_FIELDOPTIONS_STRING_PIECE = 2 } google_protobuf_FieldOptions_CType; /* Forward declarations of all message types. diff --git a/src/upb_array.h b/src/upb_array.h new file mode 100644 index 0000000000..4282a7f77a --- /dev/null +++ b/src/upb_array.h @@ -0,0 +1,66 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. + + * Defines an in-memory array type. TODO: more documentation. + * + */ + +#ifndef UPB_ARRAY_H_ +#define UPB_ARRAY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct upb_string; + +#include "upb.h" + +/* Represents an array (a repeated field) of any type. The interpretation of + * the data in the array depends on the type. */ +struct upb_array { + union upb_value_ptr elements; + uint32_t len; /* Measured in elements. */ +}; + +/* Returns a pointer to an array element. */ +INLINE union upb_value_ptr upb_array_getelementptr( + struct upb_array *arr, uint32_t n, upb_field_type_t type) +{ + union upb_value_ptr ptr; + ptr._void = (void*)((char*)arr->elements._void + n*upb_type_info[type].size); + return ptr; +} + +/* These are all overlays on upb_array, pointers between them can be cast. */ +#define UPB_DEFINE_ARRAY_TYPE(name, type) \ + struct name ## _array { \ + type *elements; \ + uint32_t len; \ + }; + +UPB_DEFINE_ARRAY_TYPE(upb_double, double) +UPB_DEFINE_ARRAY_TYPE(upb_float, float) +UPB_DEFINE_ARRAY_TYPE(upb_int32, int32_t) +UPB_DEFINE_ARRAY_TYPE(upb_int64, int64_t) +UPB_DEFINE_ARRAY_TYPE(upb_uint32, uint32_t) +UPB_DEFINE_ARRAY_TYPE(upb_uint64, uint64_t) +UPB_DEFINE_ARRAY_TYPE(upb_bool, bool) +UPB_DEFINE_ARRAY_TYPE(upb_string, struct upb_string*) +UPB_DEFINE_ARRAY_TYPE(upb_msg, void*) + +/* Defines an array of a specific message type. */ +#define UPB_MSG_ARRAY(msg_type) struct msg_type ## _array +#define UPB_DEFINE_MSG_ARRAY(msg_type) \ + UPB_MSG_ARRAY(msg_type) { \ + msg_type **elements; \ + uint32_t len; \ + }; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/upb_context.c b/src/upb_context.c index 76319cdbad..1a36d6e4ef 100644 --- a/src/upb_context.c +++ b/src/upb_context.c @@ -258,23 +258,9 @@ bool addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, return true; } -bool upb_context_addfd(struct upb_context *c, - google_protobuf_FileDescriptorProto *fd) +bool upb_context_addfds(struct upb_context *c, + google_protobuf_FileDescriptorSet *fds) { - struct upb_strtable tmp; - if(!addfd(&tmp, &c->symtab, fd, false)) { - free_symtab(&tmp); - return false; - } - upb_strtable_free(&tmp); - return true; -} - -bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) { - google_protobuf_FileDescriptorSet *fds = - upb_alloc_and_parse(c->fds_msg, fds_str, false); - if(!fds) return false; - if(fds->set_flags.has.file) { /* Insert new symbols into a temporary table until we have verified that * the descriptor is valid. */ @@ -293,6 +279,14 @@ bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) { upb_strtable_insert(&c->symtab, &e->e); upb_strtable_free(&tmp); } + return true; +} + +bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) { + google_protobuf_FileDescriptorSet *fds = + upb_alloc_and_parse(c->fds_msg, fds_str, false); + if(!fds) return false; + if(!upb_context_addfds(c, fds)) return false; /* We own fds now, need to keep a ref so we can free it later. */ if(c->fds_size == c->fds_len) { diff --git a/src/upb_context.h b/src/upb_context.h index 4ddaed6d4d..30311242f0 100644 --- a/src/upb_context.h +++ b/src/upb_context.h @@ -94,8 +94,11 @@ INLINE struct upb_symtab_entry *upb_context_symnext( * upb_context_addfd only returns true or false; it does not give any hint * about what happened in the case of failure. This is because the descriptor * is expected to have been validated at the time it was parsed/generated. */ -bool upb_context_addfd(struct upb_context *c, - struct google_protobuf_FileDescriptorProto *fd); +bool upb_context_addfds(struct upb_context *c, + struct google_protobuf_FileDescriptorSet *fds); + +bool upb_context_addfds(struct upb_context *c, + struct google_protobuf_FileDescriptorSet *fds); bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds); diff --git a/src/upb_enum.h b/src/upb_enum.h index 9fea3a4a89..cad240ac29 100644 --- a/src/upb_enum.h +++ b/src/upb_enum.h @@ -11,10 +11,7 @@ #include #include "upb_table.h" - -/* Forward declaration from descriptor.h. */ -struct google_protobuf_EnumDescriptorProto; -struct google_protobuf_EnumValueDescriptorProto; +#include "descriptor.h" struct upb_enum { struct google_protobuf_EnumDescriptorProto *descriptor; diff --git a/src/upb_msg.c b/src/upb_msg.c index 5b505413a1..deefb2787b 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -17,16 +17,6 @@ static int div_round_up(int numerator, int denominator) { return numerator > 0 ? (numerator - 1) / denominator + 1 : 0; } -static bool issubmsgtype(upb_field_type_t type) { - return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || - type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE; -} - -static bool isstringtype(upb_field_type_t type) { - return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING || - type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES; -} - /* Callback for sorting fields. */ static int compare_fields(const void *e1, const void *e2) { const google_protobuf_FieldDescriptorProto *fd1 = *(void**)e1; @@ -272,7 +262,7 @@ static upb_field_type_t tag_cb(void *udata, struct upb_tag tag, static union upb_value_ptr get_value_ptr(void *data, struct upb_msg_field *f) { union upb_value_ptr p = upb_msg_getptr(data, f); - if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { + if(upb_isarray(f)) { size_t len = upb_msg_is_set(data, f) ? (*p.arr)->len : 0; upb_msg_reuse_array(p.arr, len+1, f->type); (*p.arr)->len = len + 1; @@ -411,13 +401,13 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2, struct upb_msg_field *f, bool recursive) { if(arr1->len != arr2->len) return false; - if(issubmsgtype(f->type)) { + if(upb_issubmsg(f)) { if(!recursive) return true; for(uint32_t i = 0; i < arr1->len; i++) if(!upb_msg_eql(arr1->elements.msg[i], arr2->elements.msg[i], f->ref.msg, recursive)) return false; - } else if(isstringtype(f->type)) { + } else if(upb_isstring(f)) { for(uint32_t i = 0; i < arr1->len; i++) if(!upb_streql(arr1->elements.str[i], arr2->elements.str[i])) return false; @@ -431,7 +421,8 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2, bool upb_msg_eql(void *data1, void *data2, struct upb_msg *m, bool recursive) { - /* Must have the same fields set. */ + /* Must have the same fields set. TODO: is this wrong? Should we also + * consider absent defaults equal to explicitly set defaults? */ if(memcmp(data1, data2, m->set_flags_bytes) != 0) return false; @@ -447,7 +438,7 @@ bool upb_msg_eql(void *data1, void *data2, struct upb_msg *m, bool recursive) if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { if(!upb_array_eql(*p1.arr, *p2.arr, f, recursive)) return false; } else { - if(issubmsgtype(f->type)) { + if(upb_issubmsg(f)) { if(recursive && !upb_msg_eql(p1.msg, p2.msg, f->ref.msg, recursive)) return false; } else if(!upb_value_eql(p1, p2, f->type)) { diff --git a/src/upb_msg.h b/src/upb_msg.h index 14fc870711..0cb3cd5c27 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -101,15 +101,12 @@ #include "upb.h" #include "upb_table.h" #include "upb_parse.h" +#include "descriptor.h" #ifdef __cplusplus extern "C" { #endif -/* Forward declarations from descriptor.h. */ -struct google_protobuf_DescriptorProto; -struct google_protobuf_FieldDescriptorProto; - /* Message definition. ********************************************************/ /* Structure that describes a single field in a message. This structure is very @@ -128,6 +125,7 @@ struct upb_msg_field { /* Structure that describes a single .proto message type. */ struct upb_msg { struct google_protobuf_DescriptorProto *descriptor; + struct upb_string fqname; /* Fully qualified. */ size_t size; uint32_t num_fields; uint32_t set_flags_bytes; @@ -197,6 +195,26 @@ INLINE struct upb_msg_field *upb_msg_fieldbyname(struct upb_msg *m, return e ? &e->f : NULL; } +INLINE bool upb_issubmsgtype(upb_field_type_t type) { + return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || + type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE; +} + +INLINE bool upb_isstringtype(upb_field_type_t type) { + return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING || + type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES; +} + +INLINE bool upb_issubmsg(struct upb_msg_field *f) { + return upb_issubmsgtype(f->type); +} +INLINE bool upb_isstring(struct upb_msg_field *f) { + return upb_isstringtype(f->type); +} +INLINE bool upb_isarray(struct upb_msg_field *f) { + return f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED; +} + /* "Set" flag reading and writing. *******************************************/ INLINE size_t upb_isset_offset(uint32_t field_index) { @@ -251,49 +269,6 @@ INLINE union upb_value_ptr upb_msg_getptr(void *data, struct upb_msg_field *f) { return p; } -/* Arrays. ********************************************************************/ - -/* Represents an array (a repeated field) of any type. The interpretation of - * the data in the array depends on the type. */ -struct upb_array { - union upb_value_ptr elements; - uint32_t len; /* Measured in elements. */ -}; - -/* Returns a pointer to an array element. */ -INLINE union upb_value_ptr upb_array_getelementptr( - struct upb_array *arr, uint32_t n, upb_field_type_t type) -{ - union upb_value_ptr ptr; - ptr._void = (void*)((char*)arr->elements._void + n*upb_type_info[type].size); - return ptr; -} - -/* These are all overlays on upb_array, pointers between them can be cast. */ -#define UPB_DEFINE_ARRAY_TYPE(name, type) \ - struct name ## _array { \ - type *elements; \ - uint32_t len; \ - }; - -UPB_DEFINE_ARRAY_TYPE(upb_double, double) -UPB_DEFINE_ARRAY_TYPE(upb_float, float) -UPB_DEFINE_ARRAY_TYPE(upb_int32, int32_t) -UPB_DEFINE_ARRAY_TYPE(upb_int64, int64_t) -UPB_DEFINE_ARRAY_TYPE(upb_uint32, uint32_t) -UPB_DEFINE_ARRAY_TYPE(upb_uint64, uint64_t) -UPB_DEFINE_ARRAY_TYPE(upb_bool, bool) -UPB_DEFINE_ARRAY_TYPE(upb_string, struct upb_string*) -UPB_DEFINE_ARRAY_TYPE(upb_msg, void*) - -/* Defines an array of a specific message type. */ -#define UPB_MSG_ARRAY(msg_type) struct msg_type ## _array -#define UPB_DEFINE_MSG_ARRAY(msg_type) \ - UPB_MSG_ARRAY(msg_type) { \ - msg_type **elements; \ - uint32_t len; \ - }; - /* Memory management *********************************************************/ /* One important note about these memory management routines: they must be used