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.
pull/13171/head
Joshua Haberman 15 years ago
parent f231856c48
commit 9e3f5e343b
  1. 34
      descriptor/descriptor_const.h
  2. 68
      lang_ext/python/pb.c
  3. 3
      src/upb.h
  4. 14
      src/upb_context.c
  5. 32
      src/upb_def.c
  6. 41
      src/upb_def.h
  7. 54
      src/upb_msg.c
  8. 6
      src/upb_parse.c
  9. 44
      src/upb_text.c
  10. 11
      tests/test_vs_proto2.cc
  11. 57
      tools/upbc.c

@ -15,35 +15,35 @@ typedef enum google_protobuf_FieldOptions_CType {
} google_protobuf_FieldOptions_CType; } google_protobuf_FieldOptions_CType;
typedef enum google_protobuf_FieldDescriptorProto_Type { 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_FIXED64 = 6,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32 = 7,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL = 8, 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_MESSAGE = 11,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES = 12, 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_SFIXED64 = 16,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32 = 17, GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING = 9,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64 = 18 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; } google_protobuf_FieldDescriptorProto_Type;
typedef enum google_protobuf_FieldDescriptorProto_Label { typedef enum google_protobuf_FieldDescriptorProto_Label {
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_OPTIONAL = 1,
GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED = 2, 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; } google_protobuf_FieldDescriptorProto_Label;
typedef enum google_protobuf_FileOptions_OptimizeMode { 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; } google_protobuf_FileOptions_OptimizeMode;
#ifdef __cplusplus #ifdef __cplusplus

@ -126,38 +126,38 @@ static PyObject *upb_to_py(union upb_value_ptr p, upb_field_type_t type)
default: default:
PyErr_SetString(PyExc_RuntimeError, "internal: unexpected type"); PyErr_SetString(PyExc_RuntimeError, "internal: unexpected type");
return NULL; return NULL;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: case UPB_TYPENUM(DOUBLE):
return PyFloat_FromDouble(*p._double); return PyFloat_FromDouble(*p._double);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: case UPB_TYPENUM(FLOAT):
return PyFloat_FromDouble(*p._float); return PyFloat_FromDouble(*p._float);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: case UPB_TYPENUM(INT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: case UPB_TYPENUM(SINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: case UPB_TYPENUM(SFIXED64):
return PyLong_FromLongLong(*p.int64); return PyLong_FromLongLong(*p.int64);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: case UPB_TYPENUM(UINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: case UPB_TYPENUM(FIXED64):
return PyLong_FromUnsignedLongLong(*p.uint64); return PyLong_FromUnsignedLongLong(*p.uint64);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: case UPB_TYPENUM(SFIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: case UPB_TYPENUM(SINT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: case UPB_TYPENUM(INT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: case UPB_TYPENUM(ENUM):
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(*p.int32); return PyLong_FromLong(*p.int32);
#else #else
return PyInt_FromLong(*p.int32); return PyInt_FromLong(*p.int32);
#endif #endif
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: case UPB_TYPENUM(FIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: case UPB_TYPENUM(UINT32):
return PyLong_FromLong(*p.uint32); return PyLong_FromLong(*p.uint32);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: case UPB_TYPENUM(BOOL):
RETURN_BOOL(*p._bool); RETURN_BOOL(*p._bool);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case UPB_TYPENUM(STRING):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: case UPB_TYPENUM(BYTES):
/* Py3k will distinguish between these two. */ /* Py3k will distinguish between these two. */
return PyString_FromStringAndSize((*p.str)->ptr, (*p.str)->byte_len); return PyString_FromStringAndSize((*p.str)->ptr, (*p.str)->byte_len);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP: case UPB_TYPENUM(GROUP):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE: { case UPB_TYPENUM(MESSAGE): {
union upb_mmptr mmptr = upb_mmptr_read(p, UPB_MM_MSG_REF); union upb_mmptr mmptr = upb_mmptr_read(p, UPB_MM_MSG_REF);
bool created; bool created;
struct upb_mm_ref *ref = upb_mm_getref(mmptr, UPB_MM_MSG_REF, &pymm, &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: default:
PyErr_SetString(PyExc_RuntimeError, "internal error"); PyErr_SetString(PyExc_RuntimeError, "internal error");
return; return;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: { case UPB_TYPENUM(DOUBLE): {
PyObject *o = PyNumber_Float(val); PyObject *o = PyNumber_Float(val);
if(!o) { if(!o) {
PyErr_SetString(PyExc_ValueError, "could not convert to double"); 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); *p._double = PyFloat_AS_DOUBLE(o);
return; return;
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: { case UPB_TYPENUM(FLOAT): {
PyObject *o = PyNumber_Float(val); PyObject *o = PyNumber_Float(val);
if(!o) { if(!o) {
PyErr_SetString(PyExc_ValueError, "could not convert to float"); 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); *p._float = PyFloat_AS_DOUBLE(o);
return; return;
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: case UPB_TYPENUM(INT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: case UPB_TYPENUM(SINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: { case UPB_TYPENUM(SFIXED64): {
#if LONG_MAX >= INT64_MAX #if LONG_MAX >= INT64_MAX
bool ok; bool ok;
long longval = convert_to_long(val, INT64_MIN, INT64_MAX, &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; return;
#endif #endif
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: case UPB_TYPENUM(UINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: { case UPB_TYPENUM(FIXED64): {
PyObject *o = PyNumber_Long(val); PyObject *o = PyNumber_Long(val);
if(!o) { if(!o) {
PyErr_SetString(PyExc_ValueError, "could not convert to uint64"); 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); *p.uint64 = PyLong_AsUnsignedLongLong(o);
return; return;
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: case UPB_TYPENUM(SFIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: case UPB_TYPENUM(SINT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: case UPB_TYPENUM(INT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: { case UPB_TYPENUM(ENUM): {
bool ok; bool ok;
long longval = convert_to_long(val, INT32_MIN, INT32_MAX, &ok); long longval = convert_to_long(val, INT32_MIN, INT32_MAX, &ok);
if(ok) *p.int32 = longval; if(ok) *p.int32 = longval;
return; return;
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: case UPB_TYPENUM(FIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: { case UPB_TYPENUM(UINT32): {
#if LONG_MAX >= UINT32_MAX #if LONG_MAX >= UINT32_MAX
bool ok; bool ok;
long longval = convert_to_long(val, 0, UINT32_MAX, &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 #endif
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: case UPB_TYPENUM(BOOL):
if(!PyBool_Check(val)) { if(!PyBool_Check(val)) {
PyErr_SetString(PyExc_ValueError, "should be true or false"); PyErr_SetString(PyExc_ValueError, "should be true or false");
return; 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?"); else PyErr_SetString(PyExc_RuntimeError, "not true or false?");
return; return;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case UPB_TYPENUM(STRING):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: { case UPB_TYPENUM(BYTES): {
size_t len = PyString_GET_SIZE(val); size_t len = PyString_GET_SIZE(val);
upb_string_resize(*p.str, len); upb_string_resize(*p.str, len);
memcpy((*p.str)->ptr, PyString_AS_STRING(val), len); memcpy((*p.str)->ptr, PyString_AS_STRING(val), len);

@ -223,6 +223,9 @@ union upb_symbol_ref {
struct upb_msgdef *msg; struct upb_msgdef *msg;
struct upb_enumdef *_enum; struct upb_enumdef *_enum;
struct upb_svc *svc; 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 // Status codes used as a return value. Codes >0 are not fatal and can be

@ -243,7 +243,7 @@ static void insert_message(struct upb_strtable *t,
e.e.key = fqname; e.e.key = fqname;
e.type = UPB_SYM_MESSAGE; e.type = UPB_SYM_MESSAGE;
e.ref.msg = malloc(sizeof(*e.ref.msg)); 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)) { if(!upb_ok(status)) {
free(fqname.ptr); free(fqname.ptr);
return; return;
@ -292,14 +292,12 @@ void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs,
struct upb_msgdef *m = e->ref.msg; struct upb_msgdef *m = e->ref.msg;
for(unsigned int i = 0; i < m->num_fields; i++) { for(unsigned int i = 0; i < m->num_fields; i++) {
struct upb_fielddef *f = &m->fields[i]; struct upb_fielddef *f = &m->fields[i];
google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[i];
union upb_symbol_ref ref; union upb_symbol_ref ref;
if(fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE || if(f->type == UPB_TYPENUM(MESSAGE) || f->type == UPB_TYPENUM(GROUP))
fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP) ref = resolve2(existingdefs, addto, &e->e.key, f->ref.str,
ref = resolve2(existingdefs, addto, &e->e.key, fd->type_name,
UPB_SYM_MESSAGE); UPB_SYM_MESSAGE);
else if(fd->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM) else if(f->type == UPB_TYPENUM(ENUM))
ref = resolve2(existingdefs, addto, &e->e.key, fd->type_name, ref = resolve2(existingdefs, addto, &e->e.key, f->ref.str,
UPB_SYM_ENUM); UPB_SYM_ENUM);
else else
continue; /* No resolving necessary. */ continue; /* No resolving necessary. */
@ -307,7 +305,7 @@ void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs,
upb_seterr(status, UPB_STATUS_ERROR, upb_seterr(status, UPB_STATUS_ERROR,
"could not resolve symbol '" UPB_STRFMT "'" "could not resolve symbol '" UPB_STRFMT "'"
" in context '" 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; return;
} }
upb_msgdef_setref(m, f, ref); upb_msgdef_setref(m, f, ref);

@ -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, 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) struct upb_status *status)
{ {
(void)status; // Nothing that can fail at the moment. (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, upb_strtable_init(&m->fields_by_name, num_fields,
sizeof(struct upb_fieldsbyname_entry)); sizeof(struct upb_fieldsbyname_entry));
m->descriptor = d; m->fqname = upb_strdup(fqname);
m->fqname = fqname;
m->context = c; m->context = c;
m->num_fields = num_fields; m->num_fields = num_fields;
m->set_flags_bytes = div_round_up(m->num_fields, 8); 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->size = m->set_flags_bytes;
m->fields = malloc(sizeof(*m->fields) * m->num_fields); 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++) { for(unsigned int i = 0; i < m->num_fields; i++) {
/* We count on the caller to keep this pointer alive. */ /* 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; size_t max_align = 0;
for(unsigned int i = 0; i < m->num_fields; i++) { for(unsigned int i = 0; i < m->num_fields; i++) {
struct upb_fielddef *f = &m->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]; 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 /* 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->byte_offset = ALIGN_UP(m->size, type_info->align);
f->type = fd->type; f->type = fd->type;
f->label = fd->label; 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; m->size = f->byte_offset + type_info->size;
max_align = UPB_MAX(max_align, type_info->align); max_align = UPB_MAX(max_align, type_info->align);
if(fd->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED) 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) if(max_align > 0)
m->size = ALIGN_UP(m->size, max_align); m->size = ALIGN_UP(m->size, max_align);
free(fds);
} }
void upb_msgdef_free(struct upb_msgdef *m) void upb_msgdef_free(struct upb_msgdef *m)
{ {
upb_inttable_free(&m->fields_by_num); upb_inttable_free(&m->fields_by_num);
upb_strtable_free(&m->fields_by_name); 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->fields);
free(m->field_descriptors);
} }
void upb_msgdef_setref(struct upb_msgdef *m, struct upb_fielddef *f, void upb_msgdef_setref(struct upb_msgdef *m, struct upb_fielddef *f,
union upb_symbol_ref ref) { 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( 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 = 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); assert(int_e && str_e);
f->ref = ref; f->ref = ref;
int_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 google_protobuf_EnumDescriptorProto *ed,
struct upb_context *c) { struct upb_context *c) {
int num_values = ed->set_flags.has.value ? ed->value->len : 0; int num_values = ed->set_flags.has.value ? ed->value->len : 0;
e->descriptor = ed;
e->context = c; e->context = c;
upb_atomic_refcount_init(&e->refcount, 0); upb_atomic_refcount_init(&e->refcount, 0);
upb_strtable_init(&e->nametoint, num_values, upb_strtable_init(&e->nametoint, num_values,

@ -9,6 +9,8 @@
* - upb_enumdef: describes an enum. * - upb_enumdef: describes an enum.
* (TODO: descriptions of extensions and services). * (TODO: descriptions of extensions and services).
* *
* Defs are immutable and reference-counted.
*
* This file contains routines for creating and manipulating the definitions * This file contains routines for creating and manipulating the definitions
* themselves. To create and manipulate actual messages, see upb_msg.h. * themselves. To create and manipulate actual messages, see upb_msg.h.
*/ */
@ -27,12 +29,14 @@ extern "C" {
struct upb_fielddef; struct upb_fielddef;
struct upb_context; struct upb_context;
struct google_protobuf_EnumDescriptorProto;
struct google_protobuf_DescriptorProto;
struct google_protobuf_FieldDescriptorProto;
/* Structure that describes a single .proto message type. */ /* Structure that describes a single .proto message type. */
struct upb_msgdef { struct upb_msgdef {
struct upb_context *context; struct upb_context *context;
struct upb_msg *default_msg; /* Message with all default values set. */ 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; size_t size;
uint32_t num_fields; uint32_t num_fields;
uint32_t set_flags_bytes; uint32_t set_flags_bytes;
@ -40,19 +44,20 @@ struct upb_msgdef {
struct upb_inttable fields_by_num; struct upb_inttable fields_by_num;
struct upb_strtable fields_by_name; struct upb_strtable fields_by_name;
struct upb_fielddef *fields; struct upb_fielddef *fields;
struct google_protobuf_FieldDescriptorProto **field_descriptors;
}; };
/* Structure that describes a single field in a message. This structure is very /* Structure that describes a single field in a message. */
* 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. */
struct upb_fielddef { struct upb_fielddef {
union upb_symbol_ref ref; union upb_symbol_ref ref;
uint32_t byte_offset; /* Where to find the data. */ uint32_t byte_offset; /* Where to find the data. */
uint16_t field_index; /* Indexes upb_msgdef.fields and indicates set bit */ uint16_t field_index; /* Indicates set bit. */
upb_field_type_t type; /* Copied from descriptor for cache-friendliness. */
/* 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; upb_label_t label;
}; };
@ -89,12 +94,6 @@ INLINE upb_mm_ptrtype upb_elem_ptrtype(struct upb_fielddef *f) {
else return -1; 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. *************************************/ /* Number->field and name->field lookup. *************************************/
/* The num->field and name->field maps in upb_msgdef allow fast lookup of fields /* 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 { struct upb_enumdef {
upb_atomic_refcount_t refcount; upb_atomic_refcount_t refcount;
struct upb_context *context; struct upb_context *context;
struct google_protobuf_EnumDescriptorProto *descriptor;
struct upb_strtable nametoint; struct upb_strtable nametoint;
struct upb_inttable inttoname; struct upb_inttable inttoname;
}; };
@ -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, /* Initializes/frees a upb_msgdef. Usually this will be called by upb_context,
* and clients will not have to construct one directly. * and clients will not have to construct one directly.
* *
* Caller retains ownership of d, but the msg will contain references to it, so * Caller retains ownership of d. Note that init does not resolve
* it must outlive the msg. Note that init does not resolve
* upb_fielddef.ref the caller should do that post-initialization by * upb_fielddef.ref the caller should do that post-initialization by
* calling upb_msg_ref() below. * calling upb_msg_ref() below.
* *
* fqname indicates the fully-qualified name of this message. Ownership of * fqname indicates the fully-qualified name of this message.
* fqname passes to the msg, but the msg will contain references to it, so it
* must outlive the msg.
* *
* sort indicates whether or not it is safe to reorder the fields from the order * 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 * they appear in d. This should be false if code has been compiled against a
* header for this type that expects the given order. */ * header for this type that expects the given order. */
void upb_msgdef_init(struct upb_msgdef *m, void upb_msgdef_init(struct upb_msgdef *m,
struct google_protobuf_DescriptorProto *d, 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); struct upb_context *c, struct upb_status *status);
void upb_msgdef_free(struct upb_msgdef *m); void upb_msgdef_free(struct upb_msgdef *m);

@ -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 /* Returns a size of a value as it will be serialized. Does *not* include
* the size of the tag -- that is already accounted for. */ * the size of the tag -- that is already accounted for. */
static size_t get_valuesize(struct upb_msgsizes *sizes, union upb_value_ptr p, static size_t get_valuesize(struct upb_msgsizes *sizes, union upb_value_ptr p,
struct upb_fielddef *f, struct upb_fielddef *f)
google_protobuf_FieldDescriptorProto *fd)
{ {
switch(f->type) { switch(f->type) {
default: assert(false); return 0; /* Internal corruption. */ 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); size_t submsg_size = get_msgsize(sizes, *p.msg);
return upb_get_INT32_size(submsg_size) + submsg_size; return upb_get_INT32_size(submsg_size) + submsg_size;
} }
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP: { case UPB_TYPENUM(GROUP): {
size_t endgrp_tag_size = upb_get_tag_size(fd->number); size_t endgrp_tag_size = upb_get_tag_size(f->number);
return endgrp_tag_size + get_msgsize(sizes, *p.msg); return endgrp_tag_size + get_msgsize(sizes, *p.msg);
} }
#define CASE(type, member) \ #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. */ /* We iterate over fields and arrays in reverse order. */
for(int32_t i = m->def->num_fields - 1; i >= 0; i--) { for(int32_t i = m->def->num_fields - 1; i >= 0; i--) {
struct upb_fielddef *f = &m->def->fields[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; if(!upb_msg_isset(m, f)) continue;
union upb_value_ptr p = upb_msg_getptr(m, f); union upb_value_ptr p = upb_msg_getptr(m, f);
if(upb_isarray(f)) { if(upb_isarray(f)) {
for(int32_t j = (*p.arr)->len - 1; j >= 0; j--) { for(int32_t j = (*p.arr)->len - 1; j >= 0; j--) {
union upb_value_ptr elem = upb_array_getelementptr(*p.arr, j); union upb_value_ptr elem = upb_array_getelementptr(*p.arr, j);
/* TODO: for packed arrays tag size goes outside the loop. */ /* TODO: for packed arrays tag size goes outside the loop. */
size += upb_get_tag_size(fd->number); size += upb_get_tag_size(f->number);
size += get_valuesize(sizes, elem, f, fd); size += get_valuesize(sizes, elem, f);
} }
} else { } else {
size += upb_get_tag_size(fd->number); size += upb_get_tag_size(f->number);
size += get_valuesize(sizes, p, f, fd); size += get_valuesize(sizes, p, f);
} }
} }
/* Resize the 'sizes' array if necessary. */ /* 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]; struct upb_fielddef *f = &m->fields[i];
//union upb_value_ptr p = upb_msg_getptr(msg, f); //union upb_value_ptr p = upb_msg_getptr(msg, f);
buf = serialize_tag(buf, end, f, status); buf = serialize_tag(buf, end, f, status);
if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE) { if(f->type == UPB_TYPENUM(MESSAGE)) {
} else if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP) { } else if(f->type == UPB_TYPENUM(GROUP)) {
} else if(upb_isstring(f)) { } else if(upb_isstring(f)) {
} else { } else {
//upb_serialize_value(buf, end, f->type, p, status); //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; #define CMP(type) return *p1.type == *p2.type;
switch(type) { switch(type) {
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: case UPB_TYPENUM(DOUBLE):
CMP(_double) CMP(_double)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: case UPB_TYPENUM(FLOAT):
CMP(_float) CMP(_float)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: case UPB_TYPENUM(INT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: case UPB_TYPENUM(SFIXED64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: case UPB_TYPENUM(SINT64):
CMP(int64) CMP(int64)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: case UPB_TYPENUM(UINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: case UPB_TYPENUM(FIXED64):
CMP(uint64) CMP(uint64)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: case UPB_TYPENUM(INT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: case UPB_TYPENUM(SFIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: case UPB_TYPENUM(SINT32):
CMP(int32) CMP(int32)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: case UPB_TYPENUM(UINT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: case UPB_TYPENUM(FIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: case UPB_TYPENUM(ENUM):
CMP(uint32); CMP(uint32);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: case UPB_TYPENUM(BOOL):
CMP(_bool); CMP(_bool);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case UPB_TYPENUM(STRING):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: case UPB_TYPENUM(BYTES):
return upb_streql(*p1.str, *p2.str); return upb_streql(*p1.str, *p2.str);
default: return false; default: return false;
} }

@ -467,9 +467,9 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len,
buf = delim_end; // Could be >end. buf = delim_end; // Could be >end.
} }
} else { } else {
if(!f || !upb_check_type(tag.wire_type, f->type)) { //if(!f || !upb_check_type(tag.wire_type, f->type)) {
buf = skip_wire_value(buf, end, tag.wire_type, status); // buf = skip_wire_value(buf, end, tag.wire_type, status);
} else if (f->type == UPB_TYPENUM(GROUP)) { if (f->type == UPB_TYPENUM(GROUP)) {
submsg_end = push(p, start, 0, f, status); submsg_end = push(p, start, 0, f, status);
msgdef = p->top->msgdef; msgdef = p->top->msgdef;
} else { } else {

@ -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; #define CASE(fmtstr, member) fprintf(file, fmtstr, val.member); break;
switch(type) { switch(type) {
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE: case UPB_TYPENUM(DOUBLE):
CASE("%0.f", _double); CASE("%0.f", _double);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FLOAT: case UPB_TYPENUM(FLOAT):
CASE("%0.f", _float) CASE("%0.f", _float)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT64: case UPB_TYPENUM(INT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED64: case UPB_TYPENUM(SFIXED64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT64: case UPB_TYPENUM(SINT64):
CASE("%" PRId64, int64) CASE("%" PRId64, int64)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT64: case UPB_TYPENUM(UINT64):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED64: case UPB_TYPENUM(FIXED64):
CASE("%" PRIu64, uint64) CASE("%" PRIu64, uint64)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32: case UPB_TYPENUM(INT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SFIXED32: case UPB_TYPENUM(SFIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_SINT32: case UPB_TYPENUM(SINT32):
CASE("%" PRId32, int32) CASE("%" PRId32, int32)
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32: case UPB_TYPENUM(UINT32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIXED32: case UPB_TYPENUM(FIXED32):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_ENUM: case UPB_TYPENUM(ENUM):
CASE("%" PRIu32, uint32); CASE("%" PRIu32, uint32);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BOOL: case UPB_TYPENUM(BOOL):
CASE("%hhu", _bool); CASE("%hhu", _bool);
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case UPB_TYPENUM(STRING):
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: case UPB_TYPENUM(BYTES):
/* TODO: escaping. */ /* TODO: escaping. */
fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(val.str)); break; 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, static void printval(struct upb_text_printer *printer, union upb_value_ptr p,
struct upb_fielddef *f, struct upb_fielddef *f,
google_protobuf_FieldDescriptorProto *fd,
FILE *stream); FILE *stream);
static void printmsg(struct upb_text_printer *printer, struct upb_msg *msg, 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; struct upb_msgdef *m = msg->def;
for(uint32_t i = 0; i < m->num_fields; i++) { for(uint32_t i = 0; i < m->num_fields; i++) {
struct upb_fielddef *f = &m->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; if(!upb_msg_isset(msg, f)) continue;
union upb_value_ptr p = upb_msg_getptr(msg, f); union upb_value_ptr p = upb_msg_getptr(msg, f);
if(upb_isarray(f)) { if(upb_isarray(f)) {
struct upb_array *arr = *p.arr; struct upb_array *arr = *p.arr;
for(uint32_t j = 0; j < arr->len; j++) { for(uint32_t j = 0; j < arr->len; j++) {
union upb_value_ptr elem_p = upb_array_getelementptr(arr, 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 { } 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, static void printval(struct upb_text_printer *printer, union upb_value_ptr p,
struct upb_fielddef *f, struct upb_fielddef *f,
google_protobuf_FieldDescriptorProto *fd,
FILE *stream) FILE *stream)
{ {
if(upb_issubmsg(f)) { if(upb_issubmsg(f)) {
upb_text_push(printer, fd->name, stream); upb_text_push(printer, f->name, stream);
printmsg(printer, *p.msg, stream); printmsg(printer, *p.msg, stream);
upb_text_pop(printer, stream); upb_text_pop(printer, stream);
} else { } 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);
} }
} }

@ -135,18 +135,15 @@ void compare(const google::protobuf::Message& proto2_msg,
ASSERT((uint32_t)d->field_count() == def->num_fields); ASSERT((uint32_t)d->field_count() == def->num_fields);
for(uint32_t i = 0; i < def->num_fields; i++) { for(uint32_t i = 0; i < def->num_fields; i++) {
struct upb_fielddef *upb_f = &def->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 = const google::protobuf::FieldDescriptor *proto2_f =
d->FindFieldByNumber(upb_fd->number); d->FindFieldByNumber(upb_f->number);
// Make sure the definitions are equal. // Make sure the definitions are equal.
ASSERT(upb_f); ASSERT(upb_f);
ASSERT(upb_fd);
ASSERT(proto2_f); ASSERT(proto2_f);
ASSERT(upb_fd->number == proto2_f->number()); ASSERT(upb_f->number == proto2_f->number());
ASSERT(std::string(upb_fd->name->ptr, upb_fd->name->byte_len) == ASSERT(std::string(upb_f->name->ptr, upb_f->name->byte_len) ==
proto2_f->name()); 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()); ASSERT(upb_isarray(upb_f) == proto2_f->is_repeated());
if(!upb_msg_isset(upb_msg, upb_f)) { if(!upb_msg_isset(upb_msg, upb_f)) {

@ -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 */ for(int i = 0; i < num_entries; i++) { /* Foreach enum */
if(entries[i]->type != UPB_SYM_ENUM) continue; if(entries[i]->type != UPB_SYM_ENUM) continue;
struct upb_symtab_entry *entry = entries[i]; struct upb_symtab_entry *entry = entries[i];
struct upb_enumdef *e = entry->ref._enum; struct upb_enumdef *enumdef = entry->ref._enum;
google_protobuf_EnumDescriptorProto *ed = e->descriptor;
/* We use entry->e.key (the fully qualified name) instead of ed->name. */ /* We use entry->e.key (the fully qualified name) instead of ed->name. */
struct upb_string *enum_name = upb_strdup(&entry->e.key); struct upb_string *enum_name = upb_strdup(&entry->e.key);
to_cident(enum_name); 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); to_preproc(enum_val_prefix);
fprintf(stream, "typedef enum " UPB_STRFMT " {\n", UPB_STRARG(enum_name)); fprintf(stream, "typedef enum " UPB_STRFMT " {\n", UPB_STRARG(enum_name));
if(ed->set_flags.has.value) { struct upb_enumdef_ntoi_entry *e = upb_strtable_begin(&enumdef->nametoint);
for(uint32_t j = 0; j < ed->value->len; j++) { /* Foreach enum value. */ bool first = true;
google_protobuf_EnumValueDescriptorProto *v = ed->value->elements[j]; /* Foreach enum value. */
struct upb_string *value_name = upb_strdup(v->name); for(; e; e = upb_strtable_next(&enumdef->nametoint, &e->e)) {
struct upb_string *value_name = upb_strdup(&e->e.key);
to_preproc(value_name); to_preproc(value_name);
/* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */ /* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */
if (!first) fputs(",\n", stream);
first = false;
fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32, fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32,
UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), v->number); UPB_STRARG(enum_val_prefix), UPB_STRARG(value_name), e->value);
if(j != ed->value->len-1) fputc(',', stream);
fputc('\n', stream);
upb_string_unref(value_name); upb_string_unref(value_name);
} }
} fprintf(stream, "\n} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name));
fprintf(stream, "} " UPB_STRFMT ";\n\n", UPB_STRARG(enum_name));
upb_string_unref(enum_name); upb_string_unref(enum_name);
upb_string_unref(enum_val_prefix); 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); fputs(" struct {\n", stream);
for(uint32_t j = 0; j < m->num_fields; j++) { for(uint32_t j = 0; j < m->num_fields; j++) {
static char* labels[] = {"", "optional", "required", "repeated"}; 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", 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(" } has;\n", stream);
fputs(" } set_flags;\n", stream); fputs(" } set_flags;\n", stream);
for(uint32_t j = 0; j < m->num_fields; j++) { for(uint32_t j = 0; j < m->num_fields; j++) {
struct upb_fielddef *f = &m->fields[j]; struct upb_fielddef *f = &m->fields[j];
struct google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; if(f->type == UPB_TYPENUM(GROUP) || f->type == UPB_TYPENUM(MESSAGE)) {
if(f->type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || struct upb_string *type_name = upb_strdup(f->ref.msg->fqname);
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);
to_cident(type_name); to_cident(type_name);
if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) {
fprintf(stream, " UPB_MSG_ARRAY(" UPB_STRFMT ")* " UPB_STRFMT ";\n", 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 { } else {
fprintf(stream, " " UPB_STRFMT "* " UPB_STRFMT ";\n", 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); upb_string_unref(type_name);
} else if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { } 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*" "struct upb_int64_array*"
}; };
fprintf(stream, " %s " UPB_STRFMT ";\n", fprintf(stream, " %s " UPB_STRFMT ";\n",
c_types[fd->type], UPB_STRARG(fd->name)); c_types[f->type], UPB_STRARG(f->name));
} else { } else {
static char* c_types[] = { static char* c_types[] = {
"", "double", "float", "int64_t", "uint64_t", "int32_t", "uint64_t", "", "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" "int32_t", "int64_t"
}; };
fprintf(stream, " %s " UPB_STRFMT ";\n", 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); 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 typetable_entry *get_or_insert_typeentry(struct upb_strtable *t,
struct upb_fielddef *f) 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); upb_strdupc(upb_type_info[f->type].ctype);
struct typetable_entry *type_e = upb_strtable_lookup(t, type_name); struct typetable_entry *type_e = upb_strtable_lookup(t, type_name);
if(type_e == NULL) { 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}; union upb_value val = {.msg = data};
/* A fake field to get the recursion going. */ /* A fake field to get the recursion going. */
struct upb_fielddef fake_field = { struct upb_fielddef fake_field = {
.type = GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE, .type = UPB_TYPENUM(MESSAGE),
.ref = {.msg = m} .ref = {.msg = m}
}; };
add_value(upb_value_addrof(&val), &fake_field, &types); 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); fputs(" {.set_flags = {.has = {\n", stream);
for(unsigned int j = 0; j < m->num_fields; j++) { for(unsigned int j = 0; j < m->num_fields; j++) {
struct upb_fielddef *f = &m->fields[j]; struct upb_fielddef *f = &m->fields[j];
google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(f->name));
fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name));
if(upb_msg_isset(msgdata, f)) if(upb_msg_isset(msgdata, f))
fprintf(stream, "true"); fprintf(stream, "true");
else else
@ -533,9 +521,8 @@ static void write_message_c(void *data, struct upb_msgdef *m,
/* Print msg data. */ /* Print msg data. */
for(unsigned int j = 0; j < m->num_fields; j++) { for(unsigned int j = 0; j < m->num_fields; j++) {
struct upb_fielddef *f = &m->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); 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)) { if(!upb_msg_isset(msgdata, f)) {
fputs("0, /* Not set. */", stream); fputs("0, /* Not set. */", stream);
} else if(upb_isstring(f)) { } else if(upb_isstring(f)) {

Loading…
Cancel
Save