From 6a8dfa5f26500b90aa9ecab418abba98d1e4e356 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 4 Jan 2010 20:22:12 -0800 Subject: upb_array -> upb_arrayptr. --- src/upb.h | 16 ++++++--- src/upb_data.c | 77 +++++++++++++++++++++++++----------------- src/upb_data.h | 103 +++++++++++++++++++++++++++++++-------------------------- src/upb_def.c | 39 ++++++++++++---------- src/upb_text.c | 2 +- 5 files changed, 137 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/upb.h b/src/upb.h index 2809418..2c0a23d 100644 --- a/src/upb.h +++ b/src/upb.h @@ -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; diff --git a/src/upb_data.c b/src/upb_data.c index 58aee8a..a0a588a 100644 --- a/src/upb_data.c +++ b/src/upb_data.c @@ -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); diff --git a/src/upb_data.h b/src/upb_data.h index 88ca9af..7e24d7e 100644 --- a/src/upb_data.h +++ b/src/upb_data.h @@ -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; } diff --git a/src/upb_def.c b/src/upb_def.c index 4f57407..24a57a6 100644 --- a/src/upb_def.c +++ b/src/upb_def.c @@ -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); diff --git a/src/upb_text.c b/src/upb_text.c index 225b344..3981715 100644 --- a/src/upb_text.c +++ b/src/upb_text.c @@ -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); -- cgit v1.2.3