summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/upb_data.c22
-rw-r--r--src/upb_data.h22
-rw-r--r--src/upb_def.c14
3 files changed, 37 insertions, 21 deletions
diff --git a/src/upb_data.c b/src/upb_data.c
index 084a03c..8de0c62 100644
--- a/src/upb_data.c
+++ b/src/upb_data.c
@@ -41,7 +41,7 @@ static void data_unref(void *d, struct upb_fielddef *f) {
}
INLINE void data_init(upb_data *d, int flags) {
- d->v = flags;
+ d->v = REFCOUNT_ONE | flags;
}
static void check_not_frozen(upb_data *d) {
@@ -100,7 +100,10 @@ void upb_string_resize(upb_string *s, upb_strlen_t byte_len) {
upb_string *upb_string_getref(upb_string *s, int ref_flags) {
if(_upb_data_incref(&s->common.base, ref_flags)) return s;
- return upb_strdup(s);
+ upb_string *copy = upb_strdup(s);
+ if(ref_flags == UPB_REF_FROZEN)
+ upb_data_setflag(&copy->common.base, UPB_DATA_FROZEN);
+ return copy;
}
upb_string *upb_strreadfile(const char *filename) {
@@ -200,13 +203,18 @@ static void array_set_size(upb_array *a, upb_arraylen_t newsize) {
}
}
-void upb_array_resize(upb_array *a, upb_strlen_t len) {
+void upb_array_resize(upb_array *a, struct upb_fielddef *f, upb_strlen_t len) {
check_not_frozen(&a->common.base);
- if(array_get_size(a) < len) {
+ 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);
+ a->common.elements._void = realloc(a->common.elements._void, new_size * type_size);
array_set_size(a, new_size);
+ memset(UPB_INDEX(a->common.elements._void, old_size, type_size),
+ 0,
+ (new_size - old_size) * type_size);
}
a->common.len = len;
}
@@ -269,9 +277,11 @@ static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f)
}
upb_array_truncate(*p.arr);
upb_msg_sethas(msg, f);
+ } else {
+ assert(*p.arr);
}
upb_arraylen_t oldlen = upb_array_len(*p.arr);
- upb_array_resize(*p.arr, oldlen + 1);
+ upb_array_resize(*p.arr, f, oldlen + 1);
p = _upb_array_getptr(*p.arr, f, oldlen);
}
return p;
diff --git a/src/upb_data.h b/src/upb_data.h
index 872f237..2a7940e 100644
--- a/src/upb_data.h
+++ b/src/upb_data.h
@@ -130,8 +130,9 @@ typedef enum {
// Attempts to increment the reference on d with the given type of ref. If
// this is not possible, returns false.
INLINE bool _upb_data_incref(upb_data *d, upb_reftype reftype) {
- if((reftype == UPB_REF_FROZEN && !upb_data_hasflag(d, UPB_DATA_FROZEN)) ||
- (reftype == UPB_REF_MUTABLE && upb_data_hasflag(d, UPB_DATA_FROZEN)) ||
+ bool frozen = upb_data_hasflag(d, UPB_DATA_FROZEN);
+ if((reftype == UPB_REF_FROZEN && !frozen) ||
+ (reftype == UPB_REF_MUTABLE && frozen) ||
(upb_data_hasflag(d, UPB_DATA_HEAPALLOCATED) &&
!upb_data_hasflag(d, UPB_DATA_REFCOUNTED))) {
return false;
@@ -306,7 +307,7 @@ upb_string *upb_strreadfile(const char *filename);
// must not dynamically allocate this type.
typedef upb_string upb_static_string;
#define UPB_STRLIT_LEN(str, len) {0 | UPB_DATA_FROZEN, len, str}
-#define UPB_STRLIT(str) {{0 | UPB_DATA_FROZEN, sizeof(str), str}}
+#define UPB_STRLIT(str) {{0 | UPB_DATA_FROZEN, sizeof(str)-1, str}}
// Allows using upb_strings in printf, ie:
// upb_string str = UPB_STRLIT("Hello, World!\n");
@@ -359,6 +360,11 @@ typedef struct type ## _array { \
// empty. Caller owns one ref on it.
upb_array *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;
+}
+
// INTERNAL-ONLY:
// Frees the given message and releases references on members.
void _upb_array_free(upb_array *a, struct upb_fielddef *f);
@@ -366,7 +372,8 @@ void _upb_array_free(upb_array *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,
- struct upb_fielddef *f, int elem) {
+ struct upb_fielddef *f,
+ upb_arraylen_t elem) {
assert(elem < upb_array_len(a));
size_t type_size = upb_type_info[f->type].size;
union upb_value_ptr p = {._void = &a->common.elements.uint8[elem * type_size]};
@@ -405,11 +412,6 @@ INLINE void upb_array_append_default(upb_array *a, struct upb_fielddef *f,
union upb_value val);
#endif
-// Returns the current number of elements in the array.
-INLINE size_t upb_array_len(upb_array *a) {
- return a->common.len;
-}
-
INLINE void upb_array_truncate(upb_array *a) {
a->common.len = 0;
}
@@ -447,7 +449,7 @@ INLINE void upb_msg_unref(upb_msg *msg, struct upb_msgdef *md) {
// Tests whether the given field is explicitly set, or whether it will return
// a default.
INLINE bool upb_msg_has(upb_msg *msg, struct upb_fielddef *f) {
- return msg->data[f->field_index/8] % (1 << (f->field_index % 8));
+ return (msg->data[f->field_index/8] & (1 << (f->field_index % 8))) != 0;
}
// Returns the current value if set, or the default value if not set, of the
diff --git a/src/upb_def.c b/src/upb_def.c
index be5c181..f824910 100644
--- a/src/upb_def.c
+++ b/src/upb_def.c
@@ -287,7 +287,7 @@ static struct upb_msgdef *msgdef_new(struct upb_fielddef **fields,
m->set_flags_bytes = div_round_up(m->num_fields, 8);
// These are incremented in the loop.
m->num_required_fields = 0;
- m->size = m->set_flags_bytes;
+ m->size = m->set_flags_bytes + 4; // 4 for the refcount.
m->fields = malloc(sizeof(struct upb_fielddef) * num_fields);
size_t max_align = 0;
@@ -300,8 +300,9 @@ static struct upb_msgdef *msgdef_new(struct upb_fielddef **fields,
// multiple of that type's alignment. Also, the size of the structure as
// a whole must be a multiple of the greatest alignment of any member. */
f->field_index = i;
- f->byte_offset = ALIGN_UP(m->size, type_info->align);
- m->size = f->byte_offset + type_info->size;
+ size_t offset = ALIGN_UP(m->size, type_info->align);
+ f->byte_offset = offset - 4; // Offsets are relative to the refcount.
+ m->size = offset + type_info->size;
max_align = UPB_MAX(max_align, type_info->align);
if(f->label == UPB_LABEL(REQUIRED)) {
// We currently rely on the fact that required fields are always sorted
@@ -516,7 +517,7 @@ static void insert_message(struct upb_strtable *t,
int num_fields = d->set_flags.has.field ? d->field->len : 0;
struct symtab_ent e;
- e.e.key = fqname; // Donating our ref to the table.
+ e.e.key = fqname;
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];
@@ -530,7 +531,7 @@ static void insert_message(struct upb_strtable *t,
}
free(fielddefs);
- if(!upb_ok(status)) return;
+ if(!upb_ok(status)) goto error;
upb_strtable_insert(t, &e.e);
@@ -542,6 +543,9 @@ static void insert_message(struct upb_strtable *t,
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);
+
+error:
+ upb_string_unref(fqname);
}
static bool find_cycles(struct upb_msgdef *m, int search_depth,
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback