From 9e3f5e343b8a729331dd6448bddb9150ae60d63c Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 26 Nov 2009 20:03:07 -0800 Subject: [PATCH] Make upb_msgdef own all its data. This is in anticipation of making upb_msgdef's easy to dup. This involved removing all traces of any descriptors from the defs. --- descriptor/descriptor_const.h | 34 +++++++++--------- lang_ext/python/pb.c | 68 +++++++++++++++++------------------ src/upb.h | 3 ++ src/upb_context.c | 14 ++++---- src/upb_def.c | 32 ++++++++++------- src/upb_def.h | 45 +++++++++++------------ src/upb_msg.c | 54 ++++++++++++++-------------- src/upb_parse.c | 6 ++-- src/upb_text.c | 44 +++++++++++------------ tests/test_vs_proto2.cc | 11 +++--- tools/upbc.c | 65 ++++++++++++++------------------- 11 files changed, 179 insertions(+), 197 deletions(-) diff --git a/descriptor/descriptor_const.h b/descriptor/descriptor_const.h index 2423e977b9..36af6f92ff 100644 --- a/descriptor/descriptor_const.h +++ b/descriptor/descriptor_const.h @@ -15,35 +15,35 @@ typedef enum google_protobuf_FieldOptions_CType { } google_protobuf_FieldOptions_CType; typedef enum google_protobuf_FieldDescriptorProto_Type { - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64 = 6, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE = 11, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13, - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14, - 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_STRING = 9, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT = 2, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE = 1, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 = 5, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32 = 15, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP = 10, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64 = 3, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM = 14, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64 = 4, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18, + GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17 } 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_OPTIONAL = 1 } 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_SPEED = 1 } google_protobuf_FileOptions_OptimizeMode; #ifdef __cplusplus diff --git a/lang_ext/python/pb.c b/lang_ext/python/pb.c index 2c631840c9..0e04a6be1a 100644 --- a/lang_ext/python/pb.c +++ b/lang_ext/python/pb.c @@ -126,38 +126,38 @@ static PyObject *upb_to_py(union upb_value_ptr p, upb_field_type_t type) default: PyErr_SetString(PyExc_RuntimeError, "internal: unexpected type"); return NULL; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: + case UPB_TYPENUM(DOUBLE): return PyFloat_FromDouble(*p._double); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: + case UPB_TYPENUM(FLOAT): return PyFloat_FromDouble(*p._float); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: + case UPB_TYPENUM(INT64): + case UPB_TYPENUM(SINT64): + case UPB_TYPENUM(SFIXED64): return PyLong_FromLongLong(*p.int64); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: + case UPB_TYPENUM(UINT64): + case UPB_TYPENUM(FIXED64): return PyLong_FromUnsignedLongLong(*p.uint64); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: + case UPB_TYPENUM(SFIXED32): + case UPB_TYPENUM(SINT32): + case UPB_TYPENUM(INT32): + case UPB_TYPENUM(ENUM): #if PY_MAJOR_VERSION >= 3 return PyLong_FromLong(*p.int32); #else return PyInt_FromLong(*p.int32); #endif - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: + case UPB_TYPENUM(FIXED32): + case UPB_TYPENUM(UINT32): return PyLong_FromLong(*p.uint32); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: + case UPB_TYPENUM(BOOL): RETURN_BOOL(*p._bool); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: + case UPB_TYPENUM(STRING): + case UPB_TYPENUM(BYTES): /* Py3k will distinguish between these two. */ return PyString_FromStringAndSize((*p.str)->ptr, (*p.str)->byte_len); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE: { + case UPB_TYPENUM(GROUP): + case UPB_TYPENUM(MESSAGE): { union upb_mmptr mmptr = upb_mmptr_read(p, UPB_MM_MSG_REF); bool created; struct upb_mm_ref *ref = upb_mm_getref(mmptr, UPB_MM_MSG_REF, &pymm, &created); @@ -193,7 +193,7 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, default: PyErr_SetString(PyExc_RuntimeError, "internal error"); return; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: { + case UPB_TYPENUM(DOUBLE): { PyObject *o = PyNumber_Float(val); if(!o) { PyErr_SetString(PyExc_ValueError, "could not convert to double"); @@ -202,7 +202,7 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, *p._double = PyFloat_AS_DOUBLE(o); return; } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: { + case UPB_TYPENUM(FLOAT): { PyObject *o = PyNumber_Float(val); if(!o) { PyErr_SetString(PyExc_ValueError, "could not convert to float"); @@ -211,9 +211,9 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, *p._float = PyFloat_AS_DOUBLE(o); return; } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: { + case UPB_TYPENUM(INT64): + case UPB_TYPENUM(SINT64): + case UPB_TYPENUM(SFIXED64): { #if LONG_MAX >= INT64_MAX bool ok; long longval = convert_to_long(val, INT64_MIN, INT64_MAX, &ok); @@ -229,8 +229,8 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, return; #endif } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: { + case UPB_TYPENUM(UINT64): + case UPB_TYPENUM(FIXED64): { PyObject *o = PyNumber_Long(val); if(!o) { PyErr_SetString(PyExc_ValueError, "could not convert to uint64"); @@ -239,18 +239,18 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, *p.uint64 = PyLong_AsUnsignedLongLong(o); return; } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: { + case UPB_TYPENUM(SFIXED32): + case UPB_TYPENUM(SINT32): + case UPB_TYPENUM(INT32): + case UPB_TYPENUM(ENUM): { bool ok; long longval = convert_to_long(val, INT32_MIN, INT32_MAX, &ok); if(ok) *p.int32 = longval; return; } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: { + case UPB_TYPENUM(FIXED32): + case UPB_TYPENUM(UINT32): { #if LONG_MAX >= UINT32_MAX bool ok; long longval = convert_to_long(val, 0, UINT32_MAX, &ok); @@ -267,7 +267,7 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, #endif } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: + case UPB_TYPENUM(BOOL): if(!PyBool_Check(val)) { PyErr_SetString(PyExc_ValueError, "should be true or false"); return; @@ -277,8 +277,8 @@ static void set_upbscalarfield(union upb_value_ptr p, PyObject *val, else PyErr_SetString(PyExc_RuntimeError, "not true or false?"); return; - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: { + case UPB_TYPENUM(STRING): + case UPB_TYPENUM(BYTES): { size_t len = PyString_GET_SIZE(val); upb_string_resize(*p.str, len); memcpy((*p.str)->ptr, PyString_AS_STRING(val), len); diff --git a/src/upb.h b/src/upb.h index cc09ab140c..092ea66cbf 100644 --- a/src/upb.h +++ b/src/upb.h @@ -223,6 +223,9 @@ union upb_symbol_ref { struct upb_msgdef *msg; struct upb_enumdef *_enum; struct upb_svc *svc; + + /* Used only temporarily before a reference has been resolved. */ + struct upb_string *str; }; // Status codes used as a return value. Codes >0 are not fatal and can be diff --git a/src/upb_context.c b/src/upb_context.c index 2d558d9418..0e53ad1fa1 100644 --- a/src/upb_context.c +++ b/src/upb_context.c @@ -243,7 +243,7 @@ static void insert_message(struct upb_strtable *t, e.e.key = fqname; e.type = UPB_SYM_MESSAGE; e.ref.msg = malloc(sizeof(*e.ref.msg)); - upb_msgdef_init(e.ref.msg, d, fqname, sort, c, status); + upb_msgdef_init(e.ref.msg, d, &fqname, sort, c, status); if(!upb_ok(status)) { free(fqname.ptr); return; @@ -292,14 +292,12 @@ void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, struct upb_msgdef *m = e->ref.msg; for(unsigned int i = 0; i < m->num_fields; i++) { struct upb_fielddef *f = &m->fields[i]; - google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[i]; union upb_symbol_ref ref; - if(fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE || - fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP) - ref = resolve2(existingdefs, addto, &e->e.key, fd->type_name, + if(f->type == UPB_TYPENUM(MESSAGE) || f->type == UPB_TYPENUM(GROUP)) + ref = resolve2(existingdefs, addto, &e->e.key, f->ref.str, UPB_SYM_MESSAGE); - else if(fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM) - ref = resolve2(existingdefs, addto, &e->e.key, fd->type_name, + else if(f->type == UPB_TYPENUM(ENUM)) + ref = resolve2(existingdefs, addto, &e->e.key, f->ref.str, UPB_SYM_ENUM); else continue; /* No resolving necessary. */ @@ -307,7 +305,7 @@ void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs, upb_seterr(status, UPB_STATUS_ERROR, "could not resolve symbol '" UPB_STRFMT "'" " in context '" UPB_STRFMT "'", - UPB_STRARG(fd->type_name), UPB_STRARG(&e->e.key)); + UPB_STRARG(f->ref.str), UPB_STRARG(&e->e.key)); return; } upb_msgdef_setref(m, f, ref); diff --git a/src/upb_def.c b/src/upb_def.c index 00a0610a5b..e130563ba1 100644 --- a/src/upb_def.c +++ b/src/upb_def.c @@ -37,7 +37,7 @@ void upb_msgdef_sortfds(google_protobuf_FieldDescriptorProto **fds, size_t num) } void upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, - struct upb_string fqname, bool sort, struct upb_context *c, + struct upb_string *fqname, bool sort, struct upb_context *c, struct upb_status *status) { (void)status; // Nothing that can fail at the moment. @@ -47,8 +47,7 @@ void upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, upb_strtable_init(&m->fields_by_name, num_fields, sizeof(struct upb_fieldsbyname_entry)); - m->descriptor = d; - m->fqname = fqname; + m->fqname = upb_strdup(fqname); m->context = c; m->num_fields = num_fields; m->set_flags_bytes = div_round_up(m->num_fields, 8); @@ -57,17 +56,20 @@ void upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, m->size = m->set_flags_bytes; m->fields = malloc(sizeof(*m->fields) * m->num_fields); - m->field_descriptors = malloc(sizeof(*m->field_descriptors) * m->num_fields); + + /* Create a sorted list of the fields. */ + google_protobuf_FieldDescriptorProto **fds = + malloc(sizeof(*fds) * m->num_fields); for(unsigned int i = 0; i < m->num_fields; i++) { /* We count on the caller to keep this pointer alive. */ - m->field_descriptors[i] = d->field->elements[i]; + fds[i] = d->field->elements[i]; } - if(sort) upb_msgdef_sortfds(m->field_descriptors, m->num_fields); + if(sort) upb_msgdef_sortfds(fds, m->num_fields); size_t max_align = 0; for(unsigned int i = 0; i < m->num_fields; i++) { struct upb_fielddef *f = &m->fields[i]; - google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[i]; + google_protobuf_FieldDescriptorProto *fd = fds[i]; struct upb_type_info *type_info = &upb_type_info[fd->type]; /* General alignment rules are: each member must be at an address that is a @@ -77,6 +79,9 @@ void upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, f->byte_offset = ALIGN_UP(m->size, type_info->align); f->type = fd->type; f->label = fd->label; + f->number = fd->number; + f->name = upb_strdup(fd->name); + f->ref.str = fd->type_name; m->size = f->byte_offset + type_info->size; max_align = UPB_MAX(max_align, type_info->align); if(fd->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED) @@ -93,24 +98,26 @@ void upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, if(max_align > 0) m->size = ALIGN_UP(m->size, max_align); + free(fds); } void upb_msgdef_free(struct upb_msgdef *m) { upb_inttable_free(&m->fields_by_num); upb_strtable_free(&m->fields_by_name); + upb_string_unref(m->fqname); + for (unsigned int i = 0; i < m->num_fields; i++) { + upb_string_unref(m->fields[i].name); + } free(m->fields); - free(m->field_descriptors); } void upb_msgdef_setref(struct upb_msgdef *m, struct upb_fielddef *f, union upb_symbol_ref ref) { - struct google_protobuf_FieldDescriptorProto *d = - upb_msg_field_descriptor(f, m); struct upb_fieldsbynum_entry *int_e = upb_inttable_fast_lookup( - &m->fields_by_num, d->number, sizeof(struct upb_fieldsbynum_entry)); + &m->fields_by_num, f->number, sizeof(struct upb_fieldsbynum_entry)); struct upb_fieldsbyname_entry *str_e = - upb_strtable_lookup(&m->fields_by_name, d->name); + upb_strtable_lookup(&m->fields_by_name, f->name); assert(int_e && str_e); f->ref = ref; int_e->f.ref = ref; @@ -122,7 +129,6 @@ void upb_enumdef_init(struct upb_enumdef *e, struct google_protobuf_EnumDescriptorProto *ed, struct upb_context *c) { int num_values = ed->set_flags.has.value ? ed->value->len : 0; - e->descriptor = ed; e->context = c; upb_atomic_refcount_init(&e->refcount, 0); upb_strtable_init(&e->nametoint, num_values, diff --git a/src/upb_def.h b/src/upb_def.h index 8cbaab667f..b98eb08688 100644 --- a/src/upb_def.h +++ b/src/upb_def.h @@ -9,6 +9,8 @@ * - upb_enumdef: describes an enum. * (TODO: descriptions of extensions and services). * + * Defs are immutable and reference-counted. + * * This file contains routines for creating and manipulating the definitions * themselves. To create and manipulate actual messages, see upb_msg.h. */ @@ -27,12 +29,14 @@ extern "C" { struct upb_fielddef; struct upb_context; +struct google_protobuf_EnumDescriptorProto; +struct google_protobuf_DescriptorProto; +struct google_protobuf_FieldDescriptorProto; /* Structure that describes a single .proto message type. */ struct upb_msgdef { struct upb_context *context; struct upb_msg *default_msg; /* Message with all default values set. */ - struct google_protobuf_DescriptorProto *descriptor; - struct upb_string fqname; /* Fully qualified. */ + struct upb_string *fqname; /* Fully qualified. */ size_t size; uint32_t num_fields; uint32_t set_flags_bytes; @@ -40,19 +44,20 @@ struct upb_msgdef { struct upb_inttable fields_by_num; struct upb_strtable fields_by_name; struct upb_fielddef *fields; - struct google_protobuf_FieldDescriptorProto **field_descriptors; }; -/* Structure that describes a single field in a message. This structure is very - * consciously designed to fit into 12/16 bytes (32/64 bit, respectively), - * because copies of this struct are in the hash table that is read in the - * critical path of parsing. Minimizing the size of this struct increases - * cache-friendliness. */ +/* Structure that describes a single field in a message. */ struct upb_fielddef { union upb_symbol_ref ref; uint32_t byte_offset; /* Where to find the data. */ - uint16_t field_index; /* Indexes upb_msgdef.fields and indicates set bit */ - upb_field_type_t type; /* Copied from descriptor for cache-friendliness. */ + uint16_t field_index; /* Indicates set bit. */ + + /* TODO: Performance test whether it's better to move the name and number + * into an array in upb_msgdef, indexed by field_index. */ + upb_field_number_t number; + struct upb_string *name; + + upb_field_type_t type; upb_label_t label; }; @@ -89,12 +94,6 @@ INLINE upb_mm_ptrtype upb_elem_ptrtype(struct upb_fielddef *f) { else return -1; } -/* Can be used to retrieve a field descriptor given the upb_fielddef. */ -INLINE struct google_protobuf_FieldDescriptorProto *upb_msg_field_descriptor( - struct upb_fielddef *f, struct upb_msgdef *m) { - return m->field_descriptors[f->field_index]; -} - /* Number->field and name->field lookup. *************************************/ /* The num->field and name->field maps in upb_msgdef allow fast lookup of fields @@ -136,7 +135,6 @@ INLINE struct upb_fielddef *upb_msg_fieldbyname(struct upb_msgdef *m, struct upb_enumdef { upb_atomic_refcount_t refcount; struct upb_context *context; - struct google_protobuf_EnumDescriptorProto *descriptor; struct upb_strtable nametoint; struct upb_inttable inttoname; }; @@ -154,8 +152,8 @@ struct upb_enumdef_iton_entry { /* Initializes and frees an enum, respectively. Caller retains ownership of * ed, but it must outlive e. */ void upb_enumdef_init(struct upb_enumdef *e, - struct google_protobuf_EnumDescriptorProto *ed, - struct upb_context *c); + struct google_protobuf_EnumDescriptorProto *ed, + struct upb_context *c); void upb_enumdef_free(struct upb_enumdef *e); @@ -164,21 +162,18 @@ void upb_enumdef_free(struct upb_enumdef *e); /* Initializes/frees a upb_msgdef. Usually this will be called by upb_context, * and clients will not have to construct one directly. * - * Caller retains ownership of d, but the msg will contain references to it, so - * it must outlive the msg. Note that init does not resolve + * Caller retains ownership of d. Note that init does not resolve * upb_fielddef.ref the caller should do that post-initialization by * calling upb_msg_ref() below. * - * fqname indicates the fully-qualified name of this message. Ownership of - * fqname passes to the msg, but the msg will contain references to it, so it - * must outlive the msg. + * fqname indicates the fully-qualified name of this message. * * sort indicates whether or not it is safe to reorder the fields from the order * they appear in d. This should be false if code has been compiled against a * header for this type that expects the given order. */ void upb_msgdef_init(struct upb_msgdef *m, struct google_protobuf_DescriptorProto *d, - struct upb_string fqname, bool sort, + struct upb_string *fqname, bool sort, struct upb_context *c, struct upb_status *status); void upb_msgdef_free(struct upb_msgdef *m); diff --git a/src/upb_msg.c b/src/upb_msg.c index 3786a631a6..5f969803fa 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -173,17 +173,16 @@ static size_t get_msgsize(struct upb_msgsizes *sizes, struct upb_msg *m); /* Returns a size of a value as it will be serialized. Does *not* include * the size of the tag -- that is already accounted for. */ static size_t get_valuesize(struct upb_msgsizes *sizes, union upb_value_ptr p, - struct upb_fielddef *f, - google_protobuf_FieldDescriptorProto *fd) + struct upb_fielddef *f) { switch(f->type) { default: assert(false); return 0; /* Internal corruption. */ - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE: { + case UPB_TYPENUM(MESSAGE): { size_t submsg_size = get_msgsize(sizes, *p.msg); return upb_get_INT32_size(submsg_size) + submsg_size; } - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP: { - size_t endgrp_tag_size = upb_get_tag_size(fd->number); + case UPB_TYPENUM(GROUP): { + size_t endgrp_tag_size = upb_get_tag_size(f->number); return endgrp_tag_size + get_msgsize(sizes, *p.msg); } #define CASE(type, member) \ @@ -216,19 +215,18 @@ static size_t get_msgsize(struct upb_msgsizes *sizes, struct upb_msg *m) /* We iterate over fields and arrays in reverse order. */ for(int32_t i = m->def->num_fields - 1; i >= 0; i--) { struct upb_fielddef *f = &m->def->fields[i]; - google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, m->def); if(!upb_msg_isset(m, f)) continue; union upb_value_ptr p = upb_msg_getptr(m, f); if(upb_isarray(f)) { for(int32_t j = (*p.arr)->len - 1; j >= 0; j--) { union upb_value_ptr elem = upb_array_getelementptr(*p.arr, j); /* TODO: for packed arrays tag size goes outside the loop. */ - size += upb_get_tag_size(fd->number); - size += get_valuesize(sizes, elem, f, fd); + size += upb_get_tag_size(f->number); + size += get_valuesize(sizes, elem, f); } } else { - size += upb_get_tag_size(fd->number); - size += get_valuesize(sizes, p, f, fd); + size += upb_get_tag_size(f->number); + size += get_valuesize(sizes, p, f); } } /* Resize the 'sizes' array if necessary. */ @@ -322,8 +320,8 @@ size_t upb_msg_serialize(struct upb_msg_serialize_state *s, struct upb_fielddef *f = &m->fields[i]; //union upb_value_ptr p = upb_msg_getptr(msg, f); buf = serialize_tag(buf, end, f, status); - if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE) { - } else if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP) { + if(f->type == UPB_TYPENUM(MESSAGE)) { + } else if(f->type == UPB_TYPENUM(GROUP)) { } else if(upb_isstring(f)) { } else { //upb_serialize_value(buf, end, f->type, p, status); @@ -341,29 +339,29 @@ bool upb_value_eql(union upb_value_ptr p1, union upb_value_ptr p2, { #define CMP(type) return *p1.type == *p2.type; switch(type) { - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: + case UPB_TYPENUM(DOUBLE): CMP(_double) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: + case UPB_TYPENUM(FLOAT): CMP(_float) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: + case UPB_TYPENUM(INT64): + case UPB_TYPENUM(SFIXED64): + case UPB_TYPENUM(SINT64): CMP(int64) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: + case UPB_TYPENUM(UINT64): + case UPB_TYPENUM(FIXED64): CMP(uint64) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: + case UPB_TYPENUM(INT32): + case UPB_TYPENUM(SFIXED32): + case UPB_TYPENUM(SINT32): CMP(int32) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: + case UPB_TYPENUM(UINT32): + case UPB_TYPENUM(FIXED32): + case UPB_TYPENUM(ENUM): CMP(uint32); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: + case UPB_TYPENUM(BOOL): CMP(_bool); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: + case UPB_TYPENUM(STRING): + case UPB_TYPENUM(BYTES): return upb_streql(*p1.str, *p2.str); default: return false; } diff --git a/src/upb_parse.c b/src/upb_parse.c index 2e910f2018..3abaedf09b 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -467,9 +467,9 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len, buf = delim_end; // Could be >end. } } else { - if(!f || !upb_check_type(tag.wire_type, f->type)) { - buf = skip_wire_value(buf, end, tag.wire_type, status); - } else if (f->type == UPB_TYPENUM(GROUP)) { + //if(!f || !upb_check_type(tag.wire_type, f->type)) { + // buf = skip_wire_value(buf, end, tag.wire_type, status); + if (f->type == UPB_TYPENUM(GROUP)) { submsg_end = push(p, start, 0, f, status); msgdef = p->top->msgdef; } else { diff --git a/src/upb_text.c b/src/upb_text.c index ade8888f7e..133552c5cb 100644 --- a/src/upb_text.c +++ b/src/upb_text.c @@ -15,29 +15,29 @@ void upb_text_printval(upb_field_type_t type, union upb_value val, FILE *file) { #define CASE(fmtstr, member) fprintf(file, fmtstr, val.member); break; switch(type) { - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: + case UPB_TYPENUM(DOUBLE): CASE("%0.f", _double); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: + case UPB_TYPENUM(FLOAT): CASE("%0.f", _float) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: + case UPB_TYPENUM(INT64): + case UPB_TYPENUM(SFIXED64): + case UPB_TYPENUM(SINT64): CASE("%" PRId64, int64) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: + case UPB_TYPENUM(UINT64): + case UPB_TYPENUM(FIXED64): CASE("%" PRIu64, uint64) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: + case UPB_TYPENUM(INT32): + case UPB_TYPENUM(SFIXED32): + case UPB_TYPENUM(SINT32): CASE("%" PRId32, int32) - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: + case UPB_TYPENUM(UINT32): + case UPB_TYPENUM(FIXED32): + case UPB_TYPENUM(ENUM): CASE("%" PRIu32, uint32); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: + case UPB_TYPENUM(BOOL): CASE("%hhu", _bool); - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: - case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: + case UPB_TYPENUM(STRING): + case UPB_TYPENUM(BYTES): /* TODO: escaping. */ fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(val.str)); break; } @@ -84,7 +84,6 @@ void upb_text_pop(struct upb_text_printer *p, static void printval(struct upb_text_printer *printer, union upb_value_ptr p, struct upb_fielddef *f, - google_protobuf_FieldDescriptorProto *fd, FILE *stream); static void printmsg(struct upb_text_printer *printer, struct upb_msg *msg, @@ -93,32 +92,31 @@ static void printmsg(struct upb_text_printer *printer, struct upb_msg *msg, struct upb_msgdef *m = msg->def; for(uint32_t i = 0; i < m->num_fields; i++) { struct upb_fielddef *f = &m->fields[i]; - google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, m); if(!upb_msg_isset(msg, f)) continue; union upb_value_ptr p = upb_msg_getptr(msg, f); if(upb_isarray(f)) { struct upb_array *arr = *p.arr; for(uint32_t j = 0; j < arr->len; j++) { union upb_value_ptr elem_p = upb_array_getelementptr(arr, j); - printval(printer, elem_p, f, fd, stream); + printval(printer, elem_p, f, stream); } } else { - printval(printer, p, f, fd, stream); + printval(printer, p, f, stream); } } } static void printval(struct upb_text_printer *printer, union upb_value_ptr p, struct upb_fielddef *f, - google_protobuf_FieldDescriptorProto *fd, FILE *stream) { if(upb_issubmsg(f)) { - upb_text_push(printer, fd->name, stream); + upb_text_push(printer, f->name, stream); printmsg(printer, *p.msg, stream); upb_text_pop(printer, stream); } else { - upb_text_printfield(printer, fd->name, f->type, upb_value_read(p, f->type), stream); + upb_text_printfield(printer, f->name, f->type, + upb_value_read(p, f->type), stream); } } diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc index 8674d5879c..57cf73c562 100644 --- a/tests/test_vs_proto2.cc +++ b/tests/test_vs_proto2.cc @@ -135,18 +135,15 @@ void compare(const google::protobuf::Message& proto2_msg, ASSERT((uint32_t)d->field_count() == def->num_fields); for(uint32_t i = 0; i < def->num_fields; i++) { struct upb_fielddef *upb_f = &def->fields[i]; - struct google_protobuf_FieldDescriptorProto *upb_fd = - upb_msg_field_descriptor(upb_f, def); const google::protobuf::FieldDescriptor *proto2_f = - d->FindFieldByNumber(upb_fd->number); + d->FindFieldByNumber(upb_f->number); // Make sure the definitions are equal. ASSERT(upb_f); - ASSERT(upb_fd); ASSERT(proto2_f); - ASSERT(upb_fd->number == proto2_f->number()); - ASSERT(std::string(upb_fd->name->ptr, upb_fd->name->byte_len) == + ASSERT(upb_f->number == proto2_f->number()); + ASSERT(std::string(upb_f->name->ptr, upb_f->name->byte_len) == proto2_f->name()); - ASSERT(upb_fd->type == proto2_f->type()); + ASSERT(upb_f->type == proto2_f->type()); ASSERT(upb_isarray(upb_f) == proto2_f->is_repeated()); if(!upb_msg_isset(upb_msg, upb_f)) { diff --git a/tools/upbc.c b/tools/upbc.c index 5401d69e84..2b137e68b8 100644 --- a/tools/upbc.c +++ b/tools/upbc.c @@ -79,8 +79,7 @@ static void write_const_h(struct upb_symtab_entry *entries[], int num_entries, for(int i = 0; i < num_entries; i++) { /* Foreach enum */ if(entries[i]->type != UPB_SYM_ENUM) continue; struct upb_symtab_entry *entry = entries[i]; - struct upb_enumdef *e = entry->ref._enum; - google_protobuf_EnumDescriptorProto *ed = e->descriptor; + struct upb_enumdef *enumdef = entry->ref._enum; /* We use entry->e.key (the fully qualified name) instead of ed->name. */ struct upb_string *enum_name = upb_strdup(&entry->e.key); to_cident(enum_name); @@ -93,20 +92,20 @@ static void write_const_h(struct upb_symtab_entry *entries[], int num_entries, to_preproc(enum_val_prefix); fprintf(stream, "typedef enum " UPB_STRFMT " {\n", UPB_STRARG(enum_name)); - if(ed->set_flags.has.value) { - for(uint32_t j = 0; j < ed->value->len; j++) { /* Foreach enum value. */ - google_protobuf_EnumValueDescriptorProto *v = ed->value->elements[j]; - struct upb_string *value_name = upb_strdup(v->name); - to_preproc(value_name); - /* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */ - fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32, - UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), v->number); - if(j != ed->value->len-1) fputc(',', stream); - fputc('\n', stream); - upb_string_unref(value_name); - } + struct upb_enumdef_ntoi_entry *e = upb_strtable_begin(&enumdef->nametoint); + bool first = true; + /* Foreach enum value. */ + for(; e; e = upb_strtable_next(&enumdef->nametoint, &e->e)) { + struct upb_string *value_name = upb_strdup(&e->e.key); + to_preproc(value_name); + /* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */ + if (!first) fputs(",\n", stream); + first = false; + fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32, + UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), e->value); + upb_string_unref(value_name); } - fprintf(stream, "} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name)); + fprintf(stream, "\n} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name)); upb_string_unref(enum_name); upb_string_unref(enum_val_prefix); } @@ -178,33 +177,23 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, fputs(" struct {\n", stream); for(uint32_t j = 0; j < m->num_fields; j++) { static char* labels[] = {"", "optional", "required", "repeated"}; - struct google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; + struct upb_fielddef *f = &m->fields[j]; fprintf(stream, " bool " UPB_STRFMT ":1; /* = %" PRIu32 ", %s. */\n", - UPB_STRARG(fd->name), fd->number, labels[fd->label]); + UPB_STRARG(f->name), f->number, labels[f->label]); } fputs(" } has;\n", stream); fputs(" } set_flags;\n", stream); for(uint32_t j = 0; j < m->num_fields; j++) { struct upb_fielddef *f = &m->fields[j]; - struct google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; - if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || - f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE) { - /* Submessages get special treatment, since we have to use the message - * name directly. */ - struct upb_string type_name_ref = *fd->type_name; - if(type_name_ref.ptr[0] == UPB_SYMBOL_SEPARATOR) { - /* Omit leading '.'. */ - type_name_ref.ptr++; - type_name_ref.byte_len--; - } - struct upb_string *type_name = upb_strdup(&type_name_ref); + if(f->type == UPB_TYPENUM(GROUP) || f->type == UPB_TYPENUM(MESSAGE)) { + struct upb_string *type_name = upb_strdup(f->ref.msg->fqname); to_cident(type_name); if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { fprintf(stream, " UPB_MSG_ARRAY(" UPB_STRFMT ")* " UPB_STRFMT ";\n", - UPB_STRARG(type_name), UPB_STRARG(fd->name)); + UPB_STRARG(type_name), UPB_STRARG(f->name)); } else { fprintf(stream, " " UPB_STRFMT "* " UPB_STRFMT ";\n", - UPB_STRARG(type_name), UPB_STRARG(fd->name)); + UPB_STRARG(type_name), UPB_STRARG(f->name)); } upb_string_unref(type_name); } else if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { @@ -220,7 +209,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, "struct upb_int64_array*" }; fprintf(stream, " %s " UPB_STRFMT ";\n", - c_types[fd->type], UPB_STRARG(fd->name)); + c_types[f->type], UPB_STRARG(f->name)); } else { static char* c_types[] = { "", "double", "float", "int64_t", "uint64_t", "int32_t", "uint64_t", @@ -229,7 +218,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, "int32_t", "int64_t" }; fprintf(stream, " %s " UPB_STRFMT ";\n", - c_types[fd->type], UPB_STRARG(fd->name)); + c_types[f->type], UPB_STRARG(f->name)); } } fputs("};\n", stream); @@ -327,7 +316,7 @@ static void add_strings_from_msg(void *data, struct upb_msgdef *m, struct typetable_entry *get_or_insert_typeentry(struct upb_strtable *t, struct upb_fielddef *f) { - struct upb_string *type_name = upb_issubmsg(f) ? upb_strdup(&f->ref.msg->fqname) : + struct upb_string *type_name = upb_issubmsg(f) ? upb_strdup(f->ref.msg->fqname) : upb_strdupc(upb_type_info[f->type].ctype); struct typetable_entry *type_e = upb_strtable_lookup(t, type_name); if(type_e == NULL) { @@ -473,7 +462,7 @@ static void write_message_c(void *data, struct upb_msgdef *m, union upb_value val = {.msg = data}; /* A fake field to get the recursion going. */ struct upb_fielddef fake_field = { - .type = GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE, + .type = UPB_TYPENUM(MESSAGE), .ref = {.msg = m} }; add_value(upb_value_addrof(&val), &fake_field, &types); @@ -521,8 +510,7 @@ static void write_message_c(void *data, struct upb_msgdef *m, fputs(" {.set_flags = {.has = {\n", stream); for(unsigned int j = 0; j < m->num_fields; j++) { struct upb_fielddef *f = &m->fields[j]; - google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; - fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name)); + fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(f->name)); if(upb_msg_isset(msgdata, f)) fprintf(stream, "true"); else @@ -533,9 +521,8 @@ static void write_message_c(void *data, struct upb_msgdef *m, /* Print msg data. */ for(unsigned int j = 0; j < m->num_fields; j++) { struct upb_fielddef *f = &m->fields[j]; - google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; union upb_value val = upb_value_read(upb_msg_getptr(msgdata, f), f->type); - fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name)); + fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(f->name)); if(!upb_msg_isset(msgdata, f)) { fputs("0, /* Not set. */", stream); } else if(upb_isstring(f)) {