summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2018-09-06 18:10:45 -0700
committerJosh Haberman <jhaberman@gmail.com>2018-09-06 18:10:45 -0700
commit340bd013380f23eeb3aadd6d1eb0209c5fe7312e (patch)
tree26e11ecb0f79cf5fc2365d435a99fec0058a6787 /upb
parent3d511104acf016e1cd3ca9352193c5aeb00d4aa4 (diff)
Removed default instance and oneof array from tables.
Diffstat (limited to 'upb')
-rw-r--r--upb/decode.c28
-rw-r--r--upb/encode.c68
-rw-r--r--upb/msg.c36
-rw-r--r--upb/msg.h25
-rw-r--r--upb/msgfactory.c102
5 files changed, 59 insertions, 200 deletions
diff --git a/upb/decode.c b/upb/decode.c
index b3de9b1..aa5d721 100644
--- a/upb/decode.c
+++ b/upb/decode.c
@@ -200,19 +200,9 @@ static void *upb_array_add(upb_array *arr, size_t elements) {
return ret;
}
-static size_t get_field_offset(const upb_decframe *frame,
- const upb_msglayout_field *field) {
- if (field->oneof_index == UPB_NOT_IN_ONEOF) {
- return field->offset;
- } else {
- return frame->m->oneofs[field->oneof_index].data_offset;
- }
-}
-
static upb_array *upb_getarr(upb_decframe *frame,
const upb_msglayout_field *field) {
UPB_ASSERT(field->label == UPB_LABEL_REPEATED);
- UPB_ASSERT(field->oneof_index == UPB_NOT_IN_ONEOF);
return *(upb_array**)&frame->msg[field->offset];
}
@@ -234,20 +224,20 @@ static upb_array *upb_getorcreatearr(upb_decframe *frame,
static void upb_sethasbit(upb_decframe *frame,
const upb_msglayout_field *field) {
- UPB_ASSERT(field->hasbit != UPB_NO_HASBIT);
- frame->msg[field->hasbit / 8] |= (1 << (field->hasbit % 8));
+ UPB_ASSERT(field->presence > 0);
+ int32_t hasbit = field->presence;
+ frame->msg[hasbit / 8] |= (1 << (hasbit % 8));
}
static void upb_setoneofcase(upb_decframe *frame,
const upb_msglayout_field *field) {
- UPB_ASSERT(field->oneof_index != UPB_NOT_IN_ONEOF);
- upb_set32(frame->msg, frame->m->oneofs[field->oneof_index].case_offset,
- field->number);
+ UPB_ASSERT(field->presence < 0);
+ upb_set32(frame->msg, ~field->presence, field->number);
}
static char *upb_decode_prepareslot(upb_decframe *frame,
const upb_msglayout_field *field) {
- char *field_mem = frame->msg + get_field_offset(frame, field);
+ char *field_mem = frame->msg + field->offset;
upb_array *arr;
if (field->label == UPB_LABEL_REPEATED) {
@@ -264,9 +254,9 @@ static void upb_decode_setpresent(upb_decframe *frame,
upb_array *arr = upb_getarr(frame, field);
UPB_ASSERT(arr->len < arr->size);
arr->len++;
- } else if (field->oneof_index != UPB_NOT_IN_ONEOF) {
+ } else if (field->presence < 0) {
upb_setoneofcase(frame, field);
- } else if (field->hasbit != UPB_NO_HASBIT) {
+ } else if (field->presence > 0) {
upb_sethasbit(frame, field);
}
}
@@ -279,7 +269,6 @@ static bool upb_decode_submsg(upb_decstate *d, upb_decframe *frame,
char *submsg = *(void **)submsg_slot;
const upb_msglayout *subm;
- UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG);
subm = frame->m->submsgs[field->submsg_index];
UPB_ASSERT(subm);
@@ -460,7 +449,6 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
d->ptr -= val.size;
/* Create elemente message. */
- UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG);
subm = frame->m->submsgs[field->submsg_index];
UPB_ASSERT(subm);
diff --git a/upb/encode.c b/upb/encode.c
index 034a90d..45f8159 100644
--- a/upb/encode.c
+++ b/upb/encode.c
@@ -126,16 +126,17 @@ static bool upb_put_float(upb_encstate *e, float d) {
return upb_put_fixed32(e, u32);
}
-static uint32_t upb_readcase(const char *msg, const upb_msglayout *m,
- int oneof_index) {
+static uint32_t upb_readcase(const char *msg, const upb_msglayout_field *f) {
uint32_t ret;
- memcpy(&ret, msg + m->oneofs[oneof_index].case_offset, sizeof(ret));
+ uint32_t offset = ~f->presence;
+ memcpy(&ret, msg + offset, sizeof(ret));
return ret;
}
static bool upb_readhasbit(const char *msg, const upb_msglayout_field *f) {
- UPB_ASSERT(f->hasbit != UPB_NO_HASBIT);
- return msg[f->hasbit / 8] & (1 << (f->hasbit % 8));
+ UPB_ASSERT(f->presence > 0);
+ uint32_t hasbit = f->presence;
+ return msg[hasbit / 8] & (1 << (hasbit % 8));
}
static bool upb_put_tag(upb_encstate *e, int field_number, int wire_type) {
@@ -254,9 +255,7 @@ do { ; } while(0)
static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
const upb_msglayout *m,
const upb_msglayout_field *f,
- bool is_proto3) {
- bool skip_zero_value = is_proto3 && f->oneof_index == UPB_NOT_IN_ONEOF;
-
+ bool skip_zero_value) {
#define CASE(ctype, type, wire_type, encodeval) do { \
ctype val = *(ctype*)field_mem; \
if (skip_zero_value && val == 0) { \
@@ -305,7 +304,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
size_t size;
void *submsg = *(void **)field_mem;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
- if (skip_zero_value && submsg == NULL) {
+ if (submsg == NULL) {
return true;
}
return upb_put_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP) &&
@@ -316,7 +315,7 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
size_t size;
void *submsg = *(void **)field_mem;
const upb_msglayout *subm = m->submsgs[f->submsg_index];
- if (skip_zero_value && submsg == NULL) {
+ if (submsg == NULL) {
return true;
}
return upb_encode_message(e, submsg, subm, &size) &&
@@ -328,52 +327,33 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
UPB_UNREACHABLE();
}
-bool upb_encode_hasscalarfield(const char *msg, const upb_msglayout *m,
- const upb_msglayout_field *f) {
- if (f->oneof_index != UPB_NOT_IN_ONEOF) {
- return upb_readcase(msg, m, f->oneof_index) == f->number;
- } else if (m->is_proto2) {
- return upb_readhasbit(msg, f);
- } else {
- /* For proto3, we'll test for the field being empty later. */
- return true;
- }
-}
-
-static size_t get_field_offset2(const upb_msglayout *m,
- const upb_msglayout_field *field) {
- if (field->oneof_index == UPB_NOT_IN_ONEOF) {
- return field->offset;
- } else {
- return m->oneofs[field->oneof_index].data_offset;
- }
-}
-
bool upb_encode_message(upb_encstate *e, const char *msg,
const upb_msglayout *m, size_t *size) {
int i;
size_t pre_len = e->limit - e->ptr;
- if (msg == NULL) {
- return true;
- }
-
for (i = m->field_count - 1; i >= 0; i--) {
const upb_msglayout_field *f = &m->fields[i];
- size_t offset = get_field_offset2(m, f);
if (f->label == UPB_LABEL_REPEATED) {
- CHK(upb_encode_array(e, msg + offset, m, f));
+ CHK(upb_encode_array(e, msg + f->offset, m, f));
} else {
- if (upb_encode_hasscalarfield(msg, m, f)) {
- if (f->oneof_index == UPB_NOT_IN_ONEOF) {
- CHK(upb_encode_scalarfield(e, msg + offset, m, f, !m->is_proto2));
- } else {
- const upb_msglayout_oneof *o = &m->oneofs[f->oneof_index];
- CHK(upb_encode_scalarfield(e, msg + o->data_offset,
- m, f, !m->is_proto2));
+ bool skip_empty = false;
+ if (f->presence == 0) {
+ /* Proto3 presence. */
+ skip_empty = true;
+ } else if (f->presence > 0) {
+ /* Proto2 presence: hasbit. */
+ if (!upb_readhasbit(msg, f)) {
+ continue;
+ }
+ } else {
+ /* Field is in a oneof. */
+ if (upb_readcase(msg, f) != f->number) {
+ continue;
}
}
+ CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, skip_empty));
}
}
diff --git a/upb/msg.c b/upb/msg.c
index ca05779..b70fe40 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -148,14 +148,14 @@ static const upb_msglayout_field *upb_msg_checkfield(int field_index,
}
static bool upb_msg_inoneof(const upb_msglayout_field *field) {
- return field->oneof_index != UPB_NOT_IN_ONEOF;
+ return field->presence < 0;
}
static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
const upb_msglayout *l) {
const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
UPB_ASSERT(upb_msg_inoneof(field));
- return PTR_AT(msg, l->oneofs[field->oneof_index].case_offset, uint32_t);
+ return PTR_AT(msg, ~field->presence, uint32_t);
}
static size_t upb_msg_sizeof(const upb_msglayout *l) {
@@ -174,11 +174,7 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
msg = VOIDPTR_AT(mem, upb_msg_internalsize(l));
/* Initialize normal members. */
- if (l->default_msg) {
- memcpy(msg, l->default_msg, l->size);
- } else {
- memset(msg, 0, l->size);
- }
+ memset(msg, 0, l->size);
/* Initialize internal members. */
upb_msg_getinternal(msg)->arena = a;
@@ -199,14 +195,14 @@ bool upb_msg_has(const upb_msg *msg,
const upb_msglayout *l) {
const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
- UPB_ASSERT(l->is_proto2);
+ UPB_ASSERT(field->presence);
if (upb_msg_inoneof(field)) {
/* Oneofs are set when the oneof number is set to this field. */
return *upb_msg_oneofcase(msg, field_index, l) == field->number;
} else {
/* Other fields are set when their hasbit is set. */
- uint32_t hasbit = l->fields[field_index].hasbit;
+ uint32_t hasbit = field->presence;
return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
}
}
@@ -215,32 +211,14 @@ upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
const upb_msglayout *l) {
const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
int size = upb_msg_fieldsize(field);
-
- if (upb_msg_inoneof(field)) {
- if (*upb_msg_oneofcase(msg, field_index, l) == field->number) {
- size_t ofs = l->oneofs[field->oneof_index].data_offset;
- return upb_msgval_read(msg, ofs, size);
- } else {
- /* Return default. */
- return upb_msgval_read(l->default_msg, field->offset, size);
- }
- } else {
- return upb_msgval_read(msg, field->offset, size);
- }
+ return upb_msgval_read(msg, field->offset, size);
}
void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val,
const upb_msglayout *l) {
const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
int size = upb_msg_fieldsize(field);
-
- if (upb_msg_inoneof(field)) {
- size_t ofs = l->oneofs[field->oneof_index].data_offset;
- *upb_msg_oneofcase(msg, field_index, l) = field->number;
- upb_msgval_write(msg, ofs, val, size);
- } else {
- upb_msgval_write(msg, field->offset, val, size);
- }
+ upb_msgval_write(msg, field->offset, val, size);
}
diff --git a/upb/msg.h b/upb/msg.h
index 557a1f4..8236799 100644
--- a/upb/msg.h
+++ b/upb/msg.h
@@ -53,42 +53,25 @@ typedef void upb_msg;
* members are public so generated code can initialize them, but users MUST NOT
* read or write any of its members. */
-#define UPB_NOT_IN_ONEOF UINT16_MAX
-#define UPB_NO_HASBIT UINT16_MAX
-#define UPB_NO_SUBMSG UINT16_MAX
-
typedef struct {
uint32_t number;
- uint32_t offset; /* If in a oneof, offset of default in default_msg below. */
- uint16_t hasbit; /* UPB_NO_HASBIT if no hasbit. */
- uint16_t oneof_index; /* UPB_NOT_IN_ONEOF if not in a oneof. */
- uint16_t submsg_index; /* UPB_NO_SUBMSG if no submsg. */
+ uint16_t offset;
+ int16_t presence; /* If >0, hasbit_index+1. If <0, oneof_index+1. */
+ uint16_t submsg_index; /* undefined if descriptortype != MESSAGE or GROUP. */
uint8_t descriptortype;
uint8_t label;
} upb_msglayout_field;
-typedef struct {
- uint32_t data_offset;
- uint32_t case_offset;
-} upb_msglayout_oneof;
-
typedef struct upb_msglayout {
const struct upb_msglayout *const* submsgs;
const upb_msglayout_field *fields;
- const upb_msglayout_oneof *oneofs;
- void *default_msg;
/* Must be aligned to sizeof(void*). Doesn't include internal members like
* unknown fields, extension dict, pointer to msglayout, etc. */
- uint32_t size;
+ uint16_t size;
uint16_t field_count;
- uint16_t oneof_count;
bool extendable;
- bool is_proto2;
} upb_msglayout;
-#define UPB_ALIGN_UP_TO(val, align) ((val + (align - 1)) & -align)
-#define UPB_ALIGNED_SIZEOF(type) UPB_ALIGN_UP_TO(sizeof(type), sizeof(void*))
-
/** upb_stringview ************************************************************/
diff --git a/upb/msgfactory.c b/upb/msgfactory.c
index b544967..593c9dc 100644
--- a/upb/msgfactory.c
+++ b/upb/msgfactory.c
@@ -45,42 +45,10 @@ static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
}
}
-static upb_msgval upb_msgval_fromdefault(const upb_fielddef *f) {
- switch (upb_fielddef_type(f)) {
- case UPB_TYPE_FLOAT:
- return upb_msgval_float(upb_fielddef_defaultfloat(f));
- case UPB_TYPE_DOUBLE:
- return upb_msgval_double(upb_fielddef_defaultdouble(f));
- case UPB_TYPE_BOOL:
- return upb_msgval_bool(upb_fielddef_defaultbool(f));
- case UPB_TYPE_STRING:
- case UPB_TYPE_BYTES: {
- size_t len;
- const char *ptr = upb_fielddef_defaultstr(f, &len);
- return upb_msgval_makestr(ptr, len);
- }
- case UPB_TYPE_MESSAGE:
- return upb_msgval_msg(NULL);
- case UPB_TYPE_ENUM:
- case UPB_TYPE_INT32:
- return upb_msgval_int32(upb_fielddef_defaultint32(f));
- case UPB_TYPE_UINT32:
- return upb_msgval_uint32(upb_fielddef_defaultuint32(f));
- case UPB_TYPE_INT64:
- return upb_msgval_int64(upb_fielddef_defaultint64(f));
- case UPB_TYPE_UINT64:
- return upb_msgval_uint64(upb_fielddef_defaultuint64(f));
- default:
- UPB_ASSERT(false);
- return upb_msgval_msg(NULL);
- }
-}
-
/** upb_msglayout *************************************************************/
static void upb_msglayout_free(upb_msglayout *l) {
- upb_gfree(l->default_msg);
upb_gfree(l);
}
@@ -93,38 +61,6 @@ static size_t upb_msglayout_place(upb_msglayout *l, size_t size) {
return ret;
}
-static bool upb_msglayout_initdefault(upb_msglayout *l, const upb_msgdef *m) {
- upb_msg_field_iter it;
-
- if (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2 && l->size) {
- /* Allocate default message and set default values in it. */
- l->default_msg = upb_gmalloc(l->size);
- if (!l->default_msg) {
- return false;
- }
-
- memset(l->default_msg, 0, l->size);
-
- for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- const upb_fielddef *f = upb_msg_iter_field(&it);
-
- if (upb_fielddef_containingoneof(f)) {
- continue;
- }
-
- /* TODO(haberman): handle strings. */
- if (!upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f) &&
- !upb_fielddef_isseq(f)) {
- upb_msg_set(l->default_msg, upb_fielddef_index(f),
- upb_msgval_fromdefault(f), l);
- }
- }
- }
-
- return true;
-}
-
static bool upb_msglayout_init(const upb_msgdef *m,
upb_msglayout *l,
upb_msgfactory *factory) {
@@ -134,7 +70,6 @@ static bool upb_msglayout_init(const upb_msgdef *m,
size_t submsg_count = 0;
const upb_msglayout **submsgs;
upb_msglayout_field *fields;
- upb_msglayout_oneof *oneofs;
for (upb_msg_field_begin(&it, m);
!upb_msg_field_done(&it);
@@ -149,24 +84,18 @@ static bool upb_msglayout_init(const upb_msgdef *m,
fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields));
submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs));
- oneofs = upb_gmalloc(upb_msgdef_numoneofs(m) * sizeof(*oneofs));
if ((!fields && upb_msgdef_numfields(m)) ||
- (!submsgs && submsg_count) ||
- (!oneofs && upb_msgdef_numoneofs(m))) {
+ (!submsgs && submsg_count)) {
/* OOM. */
upb_gfree(fields);
upb_gfree(submsgs);
- upb_gfree(oneofs);
return false;
}
l->field_count = upb_msgdef_numfields(m);
- l->oneof_count = upb_msgdef_numoneofs(m);
l->fields = fields;
l->submsgs = submsgs;
- l->oneofs = oneofs;
- l->is_proto2 = (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2);
/* Allocate data offsets in three stages:
*
@@ -189,25 +118,17 @@ static bool upb_msglayout_init(const upb_msgdef *m,
field->descriptortype = upb_fielddef_descriptortype(f);
field->label = upb_fielddef_label(f);
- if (upb_fielddef_containingoneof(f)) {
- field->oneof_index = upb_oneofdef_index(upb_fielddef_containingoneof(f));
- } else {
- field->oneof_index = UPB_NOT_IN_ONEOF;
- }
-
if (upb_fielddef_issubmsg(f)) {
const upb_msglayout *sub_layout =
upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f));
field->submsg_index = submsg_count++;
submsgs[field->submsg_index] = sub_layout;
- } else {
- field->submsg_index = UPB_NO_SUBMSG;
}
if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) {
- field->hasbit = hasbit++;
+ field->presence = (hasbit++);
} else {
- field->hasbit = UPB_NO_HASBIT;
+ field->presence = 0;
}
}
@@ -237,8 +158,9 @@ static bool upb_msglayout_init(const upb_msgdef *m,
upb_oneof_iter fit;
size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */
- upb_msglayout_oneof *oneof = &oneofs[upb_oneofdef_index(o)];
size_t field_size = 0;
+ uint32_t case_offset;
+ uint32_t data_offset;
/* Calculate field size: the max of all field sizes. */
for (upb_oneof_begin(&fit, o);
@@ -249,15 +171,23 @@ static bool upb_msglayout_init(const upb_msgdef *m,
}
/* Align and allocate case offset. */
- oneof->case_offset = upb_msglayout_place(l, case_size);
- oneof->data_offset = upb_msglayout_place(l, field_size);
+ case_offset = upb_msglayout_place(l, case_size);
+ data_offset = upb_msglayout_place(l, field_size);
+
+ for (upb_oneof_begin(&fit, o);
+ !upb_oneof_done(&fit);
+ upb_oneof_next(&fit)) {
+ const upb_fielddef* f = upb_oneof_iter_field(&fit);
+ fields[upb_fielddef_index(f)].offset = data_offset;
+ fields[upb_fielddef_index(f)].presence = ~case_offset;
+ }
}
/* Size of the entire structure should be a multiple of its greatest
* alignment. TODO: track overall alignment for real? */
l->size = align_up(l->size, 8);
- return upb_msglayout_initdefault(l, m);
+ return true;
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback