upb_array -> upb_arrayptr.

pull/13171/head
Joshua Haberman 15 years ago
parent 8f2aeb8084
commit 6a8dfa5f26
  1. 16
      src/upb.h
  2. 77
      src/upb_data.c
  3. 103
      src/upb_data.h
  4. 39
      src/upb_def.c
  5. 2
      src/upb_text.c
  6. 53
      tools/upbc.c

@ -125,11 +125,10 @@ struct upb_tag {
// INTERNAL-ONLY: never refer to these types with a tag ("union", "struct").
// Always use the typedefs.
union _upb_array;
struct _upb_msg;
typedef union _upb_array upb_array;
typedef struct _upb_msg upb_msg;
typedef upb_atomic_refcount_t upb_data;
typedef uint32_t upb_strlen_t;
@ -143,6 +142,15 @@ typedef union {
upb_data *base;
} upb_strptr;
typedef uint32_t upb_arraylen_t;
typedef union {
// Must be first, for the UPB_STATIC_ARRAY_PTR_INIT() macro.
struct upb_norefcount_array *norefcount;
struct upb_refcounted_array *refcounted;
upb_data *base;
} upb_arrayptr;
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
union upb_value {
@ -154,7 +162,7 @@ union upb_value {
uint64_t uint64;
bool _bool;
upb_strptr str;
upb_array *arr;
upb_arrayptr arr;
upb_msg *msg;
upb_data *data;
};
@ -171,7 +179,7 @@ union upb_value_ptr {
uint64_t *uint64;
bool *_bool;
upb_strptr *str;
upb_array **arr;
upb_arrayptr *arr;
upb_msg **msg;
upb_data **data;
void *_void;

@ -57,11 +57,11 @@ static void check_not_frozen(upb_data *d) {
/* upb_string *******************************************************************/
static char *_upb_string_setptr(upb_strptr s, char *ptr) {
void _upb_string_setptr(upb_strptr s, char *ptr) {
if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED))
return s.refcounted->ptr = ptr;
s.refcounted->ptr = ptr;
else
return s.norefcount->ptr = ptr;
s.norefcount->ptr = ptr;
}
static void _upb_string_set_bytelen(upb_strptr s, upb_strlen_t newlen) {
@ -182,64 +182,79 @@ int upb_strcmp(upb_strptr s1, upb_strptr s2) {
/* upb_array ******************************************************************/
upb_array *upb_array_new() {
upb_array *a = malloc(sizeof(upb_refcounted_array));
data_init(&a->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
a->refcounted.size = 0;
a->common.len = 0;
a->common.elements._void = NULL;
static void _upb_array_setptr(upb_arrayptr a, void *ptr) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
a.refcounted->elements._void = ptr;
else
a.norefcount->elements._void = ptr;
}
static void _upb_array_setlen(upb_arrayptr a, upb_strlen_t newlen) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
a.refcounted->len = newlen;
} else {
a.norefcount->len = newlen;
}
}
upb_arrayptr upb_array_new() {
upb_arrayptr a;
a.refcounted = malloc(sizeof(struct upb_refcounted_array));
data_init(a.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
a.refcounted->size = 0;
a.refcounted->len = 0;
a.refcounted->elements._void = NULL;
return a;
}
// ONLY handles refcounted arrays for the moment.
void _upb_array_free(upb_array *a, struct upb_fielddef *f)
void _upb_array_free(upb_arrayptr a, struct upb_fielddef *f)
{
if(upb_elem_ismm(f)) {
for(upb_arraylen_t i = 0; i < a->refcounted.size; i++) {
for(upb_arraylen_t i = 0; i < a.refcounted->size; i++) {
union upb_value_ptr p = _upb_array_getptr(a, f, i);
if(!*p.data) continue;
data_elem_unref(p, f);
}
}
if(a->refcounted.size != 0) free(a->common.elements._void);
free(a);
if(a.refcounted->size != 0) free(a.refcounted->elements._void);
free(a.refcounted);
}
static upb_arraylen_t array_get_size(upb_array *a) {
if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
return a->refcounted.size;
static upb_arraylen_t array_get_size(upb_arrayptr a) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
return a.refcounted->size;
} else {
return (a->norefcount.size_and_flags & 0xFFFFFFF8) >> 3;
return (a.norefcount->base.v & 0xFFFFFFF8) >> 3;
}
}
static void array_set_size(upb_array *a, upb_arraylen_t newsize) {
if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
a->refcounted.size = newsize;
static void array_set_size(upb_arrayptr a, upb_arraylen_t newsize) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
a.refcounted->size = newsize;
} else {
a->norefcount.size_and_flags &= 0x7;
a->norefcount.size_and_flags |= (newsize << 3);
a.norefcount->base.v &= 0x7;
a.norefcount->base.v |= (newsize << 3);
}
}
void upb_array_resize(upb_array *a, struct upb_fielddef *f, upb_strlen_t len) {
check_not_frozen(&a->common.base);
void upb_array_resize(upb_arrayptr a, struct upb_fielddef *f, upb_strlen_t len) {
check_not_frozen(a.base);
size_t type_size = upb_type_info[f->type].size;
upb_arraylen_t old_size = array_get_size(a);
if(old_size < len) {
// Need to resize.
size_t new_size = round_up_to_pow2(len);
a->common.elements._void = realloc(a->common.elements._void, new_size * type_size);
_upb_array_setptr(a, realloc(_upb_array_getptr_raw(a, 0, 0)._void, new_size * type_size));
array_set_size(a, new_size);
memset(UPB_INDEX(a->common.elements._void, old_size, type_size),
memset(_upb_array_getptr_raw(a, old_size, type_size)._void,
0,
(new_size - old_size) * type_size);
}
a->common.len = len;
_upb_array_setlen(a, len);
}
/* upb_msg ********************************************************************/
static void upb_msg_sethas(upb_msg *msg, struct upb_fielddef *f) {
@ -289,15 +304,15 @@ static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f)
union upb_value_ptr p = _upb_msg_getptr(msg, f);
if(upb_isarray(f)) {
if(!upb_msg_has(msg, f)) {
if(!*p.arr || !upb_data_only(*p.data)) {
if(*p.arr)
if(upb_array_isnull(*p.arr) || !upb_data_only(*p.data)) {
if(!upb_array_isnull(*p.arr))
upb_array_unref(*p.arr, f);
*p.arr = upb_array_new();
}
upb_array_truncate(*p.arr);
upb_msg_sethas(msg, f);
} else {
assert(*p.arr);
assert(!upb_array_isnull(*p.arr));
}
upb_arraylen_t oldlen = upb_array_len(*p.arr);
upb_array_resize(*p.arr, f, oldlen + 1);

@ -209,9 +209,7 @@ upb_strptr upb_string_getref(upb_strptr s, int ref_flags);
#define UPB_STRING_NULL_INITIALIZER {NULL}
static const upb_strptr UPB_STRING_NULL = UPB_STRING_NULL_INITIALIZER;
INLINE bool upb_string_isnull(upb_strptr s) {
return s.base == NULL;
}
INLINE bool upb_string_isnull(upb_strptr s) { return s.base == NULL; }
// The caller releases a ref on src, which it must previously have owned a ref
// on.
@ -339,69 +337,77 @@ typedef struct upb_norefcount_string upb_static_string;
/* upb_array ******************************************************************/
typedef uint32_t upb_arraylen_t;
// The comments attached to upb_string above also apply here.
typedef struct {
upb_data base;
upb_arraylen_t len;
union upb_value_ptr elements;
} upb_array_common;
typedef struct {
uint32_t size_and_flags;
struct upb_norefcount_array {
upb_data base; // We co-opt the refcount for the size.
upb_arraylen_t len;
union upb_value_ptr elements;
} upb_norefcount_array;
};
typedef struct {
struct upb_refcounted_array {
upb_data base;
upb_arraylen_t len;
union upb_value_ptr elements;
upb_arraylen_t size;
} upb_refcounted_array;
union _upb_array {
upb_norefcount_array norefcount;
upb_array_common common;
upb_refcounted_array refcounted;
};
// This type can be used either to perform read-only access on an array,
// or to statically define a non-reference-counted static array.
#define UPB_DEFINE_MSG_ARRAY(type) \
typedef struct type ## _array { \
upb_data base; \
upb_arraylen_t len;\
type **elements; \
} type ## _array; \
typedef struct upb_norefcount_array upb_static_array;
#define UPB_STATIC_ARRAY_INIT(arr, len) {{0 | UPB_DATA_FROZEN}, len, {._void=arr}}
#define UPB_STATIC_ARRAY_PTR_TYPED_INIT(static_arr) {{&static_arr}}
#define UPB_ARRAY_NULL_INITIALIZER {NULL}
static const upb_arrayptr UPB_ARRAY_NULL = UPB_ARRAY_NULL_INITIALIZER;
INLINE bool upb_array_isnull(upb_arrayptr a) { return a.base == NULL; }
INLINE bool upb_array_ptreql(upb_arrayptr a1, upb_arrayptr a2) {
return a1.base == a2.base;
}
#define UPB_MSG_ARRAY(type) struct type ## _array
#define UPB_MSG_ARRAYPTR(type) type ## _array
#define UPB_DEFINE_MSG_ARRAY(type) \
typedef struct { upb_arrayptr ptr; } UPB_MSG_ARRAYPTR(type); \
INLINE upb_arraylen_t type ## _array_len(UPB_MSG_ARRAYPTR(type) a) { \
return upb_array_len(a.ptr); \
} \
INLINE type* type ## _array_get(UPB_MSG_ARRAYPTR(type) a, upb_arraylen_t elem) { \
return *(type**)_upb_array_getptr_raw(a.ptr, elem, sizeof(void*))._void; \
}
// Constructs a newly-allocated, reference-counted array which starts out
// empty. Caller owns one ref on it.
upb_array *upb_array_new(void);
upb_arrayptr upb_array_new(void);
// Returns the current number of elements in the array.
INLINE size_t upb_array_len(upb_array *a) {
return a->common.len;
INLINE size_t upb_array_len(upb_arrayptr a) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
return a.refcounted->len;
else
return a.norefcount->len;
}
// INTERNAL-ONLY:
// Frees the given message and releases references on members.
void _upb_array_free(upb_array *a, struct upb_fielddef *f);
void _upb_array_free(upb_arrayptr a, struct upb_fielddef *f);
// INTERNAL-ONLY:
// Returns a pointer to the given elem.
INLINE union upb_value_ptr _upb_array_getptr(upb_array *a,
INLINE union upb_value_ptr _upb_array_getptr_raw(upb_arrayptr a,
upb_arraylen_t elem,
size_t type_size) {
union upb_value_ptr p;
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
p._void = &a.refcounted->elements.uint8[elem * type_size];
else
p._void = &a.norefcount->elements.uint8[elem * type_size];
return p;
}
INLINE union upb_value_ptr _upb_array_getptr(upb_arrayptr a,
struct upb_fielddef *f,
upb_arraylen_t elem) {
size_t type_size = upb_type_info[f->type].size;
union upb_value_ptr p = {._void = &a->common.elements.uint8[elem * type_size]};
return p;
return _upb_array_getptr_raw(a, elem, upb_type_info[f->type].size);
}
INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
INLINE union upb_value upb_array_get(upb_arrayptr a, struct upb_fielddef *f,
upb_arraylen_t elem) {
assert(elem < upb_array_len(a));
return upb_value_read(_upb_array_getptr(a, f, elem), f->type);
@ -409,33 +415,36 @@ INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
// The caller releases a ref on the given array, which it must previously have
// owned a ref on.
INLINE void upb_array_unref(upb_array *a, struct upb_fielddef *f) {
if(_upb_data_unref(&a->common.base)) _upb_array_free(a, f);
INLINE void upb_array_unref(upb_arrayptr a, struct upb_fielddef *f) {
if(_upb_data_unref(a.base)) _upb_array_free(a, f);
}
#if 0
// Returns an array to which caller owns a ref, and contains the same contents
// as src. The returned value may be a copy of src, if the requested flags
// were incompatible with src's.
INLINE upb_array *upb_array_getref(upb_array *src, int ref_flags);
INLINE upb_arrayptr upb_array_getref(upb_arrayptr src, int ref_flags);
// Sets the given element in the array to val. The current length of the array
// must be greater than elem. If the field type is dynamic, the array will
// take a ref on val and release a ref on what was previously in the array.
INLINE void upb_array_set(upb_array *a, struct upb_fielddef *f, int elem,
INLINE void upb_array_set(upb_arrayptr a, struct upb_fielddef *f, int elem,
union upb_value val);
// Note that array_append will attempt to take a reference on the given value,
// so to avoid a copy use append_default and get.
INLINE void upb_array_append(upb_array *a, struct upb_fielddef *f,
INLINE void upb_array_append(upb_arrayptr a, struct upb_fielddef *f,
union upb_value val);
INLINE void upb_array_append_default(upb_array *a, struct upb_fielddef *f,
INLINE void upb_array_append_default(upb_arrayptr a, struct upb_fielddef *f,
union upb_value val);
#endif
INLINE void upb_array_truncate(upb_array *a) {
a->common.len = 0;
INLINE void upb_array_truncate(upb_arrayptr a) {
if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
a.refcounted->len = 0;
else
a.norefcount->len = 0;
}

@ -364,12 +364,14 @@ static struct upb_enumdef *enumdef_new(google_protobuf_EnumDescriptorProto *ed,
{
struct upb_enumdef *e = malloc(sizeof(*e));
upb_def_init(&e->base, UPB_DEF_ENUM, fqname);
int num_values = ed->set_flags.has.value ? ed->value->len : 0;
int num_values = ed->set_flags.has.value ?
google_protobuf_EnumValueDescriptorProto_array_len(ed->value) : 0;
upb_strtable_init(&e->ntoi, num_values, sizeof(struct ntoi_ent));
upb_inttable_init(&e->iton, num_values, sizeof(struct iton_ent));
for(int i = 0; i < num_values; i++) {
google_protobuf_EnumValueDescriptorProto *value = ed->value->elements[i];
google_protobuf_EnumValueDescriptorProto *value =
google_protobuf_EnumValueDescriptorProto_array_get(ed->value, i);
struct ntoi_ent ntoi_ent = {{value->name, 0}, value->number};
struct iton_ent iton_ent = {{value->number, 0}, value->name};
upb_strtable_insert(&e->ntoi, &ntoi_ent.e);
@ -521,20 +523,22 @@ static void insert_message(struct upb_strtable *t,
upb_strptr fqname = try_define(t, base, name, status);
if(upb_string_isnull(fqname)) return;
int num_fields = d->set_flags.has.field ? d->field->len : 0;
int num_fields = d->set_flags.has.field ?
google_protobuf_FieldDescriptorProto_array_len(d->field) : 0;
struct symtab_ent e;
e.e.key = fqname;
// Gather our list of fields, sorting if necessary.
struct upb_fielddef **fielddefs = malloc(sizeof(*fielddefs) * num_fields);
for (int i = 0; i < num_fields; i++) {
google_protobuf_FieldDescriptorProto *fd = d->field->elements[i];
google_protobuf_FieldDescriptorProto *fd =
google_protobuf_FieldDescriptorProto_array_get(d->field, i);
fielddefs[i] = fielddef_new(fd);
}
if(sort) fielddef_sort(fielddefs, d->field->len);
if(sort) fielddef_sort(fielddefs, num_fields);
// Create the msgdef with that list of fields.
e.def = UPB_UPCAST(msgdef_new(fielddefs, d->field->len, fqname, status));
e.def = UPB_UPCAST(msgdef_new(fielddefs, num_fields, fqname, status));
// Cleanup.
for (int i = 0; i < num_fields; i++) fielddef_free(fielddefs[i]);
@ -546,12 +550,12 @@ static void insert_message(struct upb_strtable *t,
/* Add nested messages and enums. */
if(d->set_flags.has.nested_type)
for(unsigned int i = 0; i < d->nested_type->len; i++)
insert_message(t, d->nested_type->elements[i], fqname, sort, status);
for(unsigned int i = 0; i < google_protobuf_DescriptorProto_array_len(d->nested_type); i++)
insert_message(t, google_protobuf_DescriptorProto_array_get(d->nested_type, i), fqname, sort, status);
if(d->set_flags.has.enum_type)
for(unsigned int i = 0; i < d->enum_type->len; i++)
insert_enum(t, d->enum_type->elements[i], fqname, status);
for(unsigned int i = 0; i < google_protobuf_EnumDescriptorProto_array_len(d->enum_type); i++)
insert_enum(t, google_protobuf_EnumDescriptorProto_array_get(d->enum_type, i), fqname, status);
error:
// Free the ref we got from try_define().
@ -618,12 +622,12 @@ static void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs,
}
if(fd->set_flags.has.message_type)
for(unsigned int i = 0; i < fd->message_type->len; i++)
insert_message(addto, fd->message_type->elements[i], pkg, sort, status);
for(unsigned int i = 0; i < google_protobuf_DescriptorProto_array_len(fd->message_type); i++)
insert_message(addto, google_protobuf_DescriptorProto_array_get(fd->message_type, i), pkg, sort, status);
if(fd->set_flags.has.enum_type)
for(unsigned int i = 0; i < fd->enum_type->len; i++)
insert_enum(addto, fd->enum_type->elements[i], pkg, status);
for(unsigned int i = 0; i < google_protobuf_EnumDescriptorProto_array_len(fd->enum_type); i++)
insert_enum(addto, google_protobuf_EnumDescriptorProto_array_get(fd->enum_type, i), pkg, status);
upb_string_unref(pkg);
@ -686,8 +690,9 @@ struct upb_symtab *upb_symtab_new()
upb_strtable_init(&s->psymtab, 16, sizeof(struct symtab_ent));
// Add descriptor.proto types to private symtable so we can parse descriptors.
// We know there is only 1.
google_protobuf_FileDescriptorProto *fd =
upb_file_descriptor_set->file->elements[0]; // We know there is only 1.
google_protobuf_FileDescriptorProto_array_get(upb_file_descriptor_set->file, 0);
struct upb_status status = UPB_STATUS_INIT;
addfd(&s->psymtab, &s->symtab, fd, false, &status);
if(!upb_ok(&status)) {
@ -782,8 +787,8 @@ void upb_symtab_addfds(struct upb_symtab *s,
{ // Read lock scope
upb_rwlock_rdlock(&s->lock);
for(uint32_t i = 0; i < fds->file->len; i++) {
addfd(&tmp, &s->symtab, fds->file->elements[i], true, status);
for(uint32_t i = 0; i < google_protobuf_FileDescriptorProto_array_len(fds->file); i++) {
addfd(&tmp, &s->symtab, google_protobuf_FileDescriptorProto_array_get(fds->file, i), true, status);
if(!upb_ok(status)) {
free_symtab(&tmp);
upb_rwlock_unlock(&s->lock);

@ -92,7 +92,7 @@ static void printmsg(struct upb_text_printer *printer,
if(!upb_msg_has(msg, f)) continue;
union upb_value v = upb_msg_get(msg, f);
if(upb_isarray(f)) {
upb_array *arr = v.arr;
upb_arrayptr arr = v.arr;
for(uint32_t j = 0; j < upb_array_len(arr); j++) {
union upb_value elem = upb_array_get(arr, f, j);
printval(printer, elem, f, stream);

@ -158,8 +158,10 @@ static void write_h(struct upb_def *defs[], int num_defs, char *outfile_name,
upb_strptr msg_name = upb_strdup(UPB_UPCAST(m)->fqname);
to_cident(msg_name);
fprintf(stream, "struct " UPB_STRFMT ";\n", UPB_STRARG(msg_name));
fprintf(stream, "typedef struct " UPB_STRFMT "\n " UPB_STRFMT ";\n\n",
fprintf(stream, "typedef struct " UPB_STRFMT "\n " UPB_STRFMT ";\n",
UPB_STRARG(msg_name), UPB_STRARG(msg_name));
fprintf(stream, "UPB_DEFINE_MSG_ARRAY(" UPB_STRFMT ")\n\n",
UPB_STRARG(msg_name));
upb_string_unref(msg_name);
}
@ -189,7 +191,7 @@ static void write_h(struct upb_def *defs[], int num_defs, char *outfile_name,
upb_strptr type_name = upb_strdup(f->def->fqname);
to_cident(type_name);
if(f->label == UPB_LABEL(REPEATED)) {
fprintf(stream, " UPB_MSG_ARRAY(" UPB_STRFMT ")* " UPB_STRFMT ";\n",
fprintf(stream, " UPB_MSG_ARRAYPTR(" UPB_STRFMT ") " UPB_STRFMT ";\n",
UPB_STRARG(type_name), UPB_STRARG(f->name));
} else {
fprintf(stream, " " UPB_STRFMT "* " UPB_STRFMT ";\n",
@ -197,7 +199,7 @@ static void write_h(struct upb_def *defs[], int num_defs, char *outfile_name,
}
upb_string_unref(type_name);
} else if(f->label == UPB_LABEL(REPEATED)) {
fprintf(stream, " upb_array* " UPB_STRFMT ";\n", UPB_STRARG(f->name));
fprintf(stream, " upb_arrayptr " UPB_STRFMT ";\n", UPB_STRARG(f->name));
} else {
static char* c_types[] = {
"", "double", "float", "int64_t", "uint64_t", "int32_t", "uint64_t",
@ -209,9 +211,7 @@ static void write_h(struct upb_def *defs[], int num_defs, char *outfile_name,
c_types[f->type], UPB_STRARG(f->name));
}
}
fputs("};\n", stream);
fprintf(stream, "UPB_DEFINE_MSG_ARRAY(" UPB_STRFMT ")\n\n",
UPB_STRARG(msg_name));
fputs("};\n\n", stream);
upb_string_unref(msg_name);
}
@ -241,7 +241,7 @@ struct typetable_entry {
struct array {
int offset;
int len;
upb_array *ptr; /* So we can find it later. */
upb_arrayptr ptr; /* So we can find it later. */
} *arrays;
int arrays_size, arrays_len;
};
@ -287,7 +287,7 @@ static void add_strings_from_msg(upb_msg *msg, struct upb_msgdef *md,
if(!upb_msg_has(msg, f)) continue;
union upb_value p = upb_msg_get(msg, f);
if(upb_isarray(f)) {
upb_array *arr = p.arr;
upb_arrayptr arr = p.arr;
for(uint32_t j = 0; j < upb_array_len(arr); j++)
add_strings_from_value(upb_array_get(arr, f, j), f, t);
} else {
@ -345,7 +345,7 @@ static void add_submsgs(upb_msg *msg, struct upb_msgdef *md,
union upb_value v = upb_msg_get(msg, f);
if(upb_isarray(f)) {
if(upb_isstring(f)) continue; /* Handled by a different code-path. */
upb_array *arr = v.arr;
upb_arrayptr arr = v.arr;
/* Add to our list of arrays for this type. */
struct typetable_entry *arr_type_e =
@ -475,11 +475,11 @@ static void write_message_c(upb_msg *msg, struct upb_msgdef *md,
fprintf(stream, "};\n");
int cum_offset = 0;
fprintf(stream, "static UPB_MSG_ARRAY(" UPB_STRFMT ") " UPB_STRFMT "_arrays[%d] = {\n",
UPB_STRARG(e->cident), UPB_STRARG(e->cident), e->arrays_len);
fprintf(stream, "static upb_static_array " UPB_STRFMT "_arrays[%d] = {\n",
UPB_STRARG(e->cident), e->arrays_len);
for(int i = 0; i < e->arrays_len; i++) {
struct array *arr = &e->arrays[i];
fprintf(stream, " {.elements = &" UPB_STRFMT "_array_elems[%d], .len=%d},\n",
fprintf(stream, " UPB_STATIC_ARRAY_INIT(&" UPB_STRFMT "_array_elems[%d], %d),\n",
UPB_STRARG(e->cident), cum_offset, arr->len);
cum_offset += arr->len;
}
@ -515,7 +515,12 @@ static void write_message_c(upb_msg *msg, struct upb_msgdef *md,
union upb_value val = upb_msg_get(msgdata, f);
fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(f->name));
if(!upb_msg_has(msgdata, f)) {
if(upb_isstring(f) && !upb_isarray(f)) {
if(upb_isarray(f) && upb_issubmsg(f)) {
// This is gross and needs cleanup.
fputs("{UPB_ARRAY_NULL_INITIALIZER}, /* Not set. */", stream);
} else if(upb_isarray(f)) {
fputs("UPB_ARRAY_NULL_INITIALIZER, /* Not set. */", stream);
} else if(upb_isstring(f)) {
fputs("UPB_STRING_NULL_INITIALIZER, /* Not set. */", stream);
} else {
fputs("0, /* Not set. */", stream);
@ -536,13 +541,13 @@ static void write_message_c(upb_msg *msg, struct upb_msgdef *md,
assert(type_e);
int arr_num = -1;
for(int k = 0; k < type_e->arrays_len; k++) {
if(type_e->arrays[k].ptr == val.arr) {
if(upb_array_ptreql(type_e->arrays[k].ptr, val.arr)) {
arr_num = k;
break;
}
}
assert(arr_num != -1);
fprintf(stream, "&" UPB_STRFMT "_arrays[%d],", UPB_STRARG(type_e->cident), arr_num);
fprintf(stream, "UPB_STATIC_ARRAY_PTR_TYPED_INIT(" UPB_STRFMT "_arrays[%d]),", UPB_STRARG(type_e->cident), arr_num);
} else if(upb_issubmsg(f)) {
/* Find this submessage in the list of msgs for that type. */
struct typetable_entry *type_e = get_or_insert_typeentry(&types, f);
@ -625,10 +630,14 @@ void error(char *err, ...)
void sort_fields_in_descriptor(google_protobuf_DescriptorProto *d)
{
if(d->set_flags.has.field) upb_fielddef_sortfds(d->field->elements, d->field->len);
// XXX: modifying the array in place is totally not allowed.
if(d->set_flags.has.field) {
upb_fielddef_sortfds(_upb_array_getptr_raw(d->field.ptr, 0, 0)._void,
google_protobuf_FieldDescriptorProto_array_len(d->field));
}
if(d->set_flags.has.nested_type)
for(uint32_t i = 0; i < d->nested_type->len; i++)
sort_fields_in_descriptor(d->nested_type->elements[i]);
for(uint32_t i = 0; i < google_protobuf_DescriptorProto_array_len(d->nested_type); i++)
sort_fields_in_descriptor(google_protobuf_DescriptorProto_array_get(d->nested_type, i));
}
int main(int argc, char *argv[])
@ -686,11 +695,11 @@ int main(int argc, char *argv[])
// this scheme.
//
// If/when we ever make upbc more general, we'll have to revisit this.
for(uint32_t i = 0; i < fds->file->len; i++) {
google_protobuf_FileDescriptorProto *fd = fds->file->elements[i];
for(uint32_t i = 0; i < google_protobuf_FileDescriptorProto_array_len(fds->file); i++) {
google_protobuf_FileDescriptorProto *fd = google_protobuf_FileDescriptorProto_array_get(fds->file, i);
if(!fd->set_flags.has.message_type) continue;
for(uint32_t j = 0; j < fd->message_type->len; j++)
sort_fields_in_descriptor(fd->message_type->elements[j]);
for(uint32_t j = 0; j < google_protobuf_DescriptorProto_array_len(fd->message_type); j++)
sort_fields_in_descriptor(google_protobuf_DescriptorProto_array_get(fd->message_type, j));
}
/* Emit output files. */

Loading…
Cancel
Save