summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2018-08-22 23:15:12 -0700
committerJosh Haberman <jhaberman@gmail.com>2018-08-22 23:15:12 -0700
commite94ac4f75717f2bd1a617e5633cd502106748475 (patch)
treea010d942478fa846d35de106373a39076c15aace /upb
parent0a95f73d0d9874151c0d36d6035230a873fa1715 (diff)
Moved upb_msg parts that depend on def to a separate msgfactory.{c,h}.
Also got rid of the premature "v1" business that was attempting to create a binary compatibility story. Also added an in-progress CMakeLists.txt file.
Diffstat (limited to 'upb')
-rw-r--r--upb/bindings/lua/upb.h1
-rw-r--r--upb/decode.c55
-rw-r--r--upb/decode.h4
-rw-r--r--upb/encode.c46
-rw-r--r--upb/encode.h4
-rw-r--r--upb/msg.c354
-rw-r--r--upb/msg.h115
-rw-r--r--upb/msgfactory.c325
-rw-r--r--upb/msgfactory.h40
9 files changed, 474 insertions, 470 deletions
diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h
index 52bc5a2..820a317 100644
--- a/upb/bindings/lua/upb.h
+++ b/upb/bindings/lua/upb.h
@@ -9,6 +9,7 @@
#include "upb/def.h"
#include "upb/handlers.h"
#include "upb/msg.h"
+#include "upb/msgfactory.h"
/* Lua 5.1/5.2 compatibility code. */
#if LUA_VERSION_NUM == 501
diff --git a/upb/decode.c b/upb/decode.c
index ca18e95..8a29709 100644
--- a/upb/decode.c
+++ b/upb/decode.c
@@ -41,7 +41,7 @@ typedef struct {
/* These members are unset for an unknown group frame. */
char *msg;
- const upb_msglayout_msginit_v1 *m;
+ const upb_msglayout *m;
} upb_decframe;
#define CHK(x) if (!(x)) { return false; }
@@ -50,7 +50,7 @@ static bool upb_skip_unknowngroup(upb_decstate *d, int field_number,
const char *limit);
static bool upb_decode_message(upb_decstate *d, const char *limit,
int group_number, char *msg,
- const upb_msglayout_msginit_v1 *l);
+ const upb_msglayout *l);
static bool upb_decode_varint(const char **ptr, const char *limit,
uint64_t *val) {
@@ -202,14 +202,13 @@ static void *upb_array_add(upb_array *arr, size_t elements) {
}
static upb_array *upb_getarr(upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
UPB_ASSERT(field->label == UPB_LABEL_REPEATED);
return *(upb_array**)&frame->msg[field->offset];
}
-static upb_array *upb_getorcreatearr(upb_decstate *d,
- upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+static upb_array *upb_getorcreatearr(upb_decstate *d, upb_decframe *frame,
+ const upb_msglayout_field *field) {
upb_array *arr = upb_getarr(frame, field);
if (!arr) {
@@ -225,21 +224,20 @@ static upb_array *upb_getorcreatearr(upb_decstate *d,
}
static void upb_sethasbit(upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
UPB_ASSERT(field->hasbit != UPB_NO_HASBIT);
frame->msg[field->hasbit / 8] |= (1 << (field->hasbit % 8));
}
static void upb_setoneofcase(upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+ 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);
}
-static char *upb_decode_prepareslot(upb_decstate *d,
- upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+static char *upb_decode_prepareslot(upb_decstate *d, upb_decframe *frame,
+ const upb_msglayout_field *field) {
char *field_mem = frame->msg + field->offset;
upb_array *arr;
@@ -252,7 +250,7 @@ static char *upb_decode_prepareslot(upb_decstate *d,
}
static void upb_decode_setpresent(upb_decframe *frame,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
if (field->label == UPB_LABEL_REPEATED) {
upb_array *arr = upb_getarr(frame, field);
UPB_ASSERT(arr->len < arr->size);
@@ -264,14 +262,13 @@ static void upb_decode_setpresent(upb_decframe *frame,
}
}
-static bool upb_decode_submsg(upb_decstate *d,
- upb_decframe *frame,
+static bool upb_decode_submsg(upb_decstate *d, upb_decframe *frame,
const char *limit,
- const upb_msglayout_fieldinit_v1 *field,
+ const upb_msglayout_field *field,
int group_number) {
char *submsg_slot = upb_decode_prepareslot(d, frame, field);
- char *submsg = *(void**)submsg_slot;
- const upb_msglayout_msginit_v1 *subm;
+ char *submsg = *(void **)submsg_slot;
+ const upb_msglayout *subm;
UPB_ASSERT(field->submsg_index != UPB_NO_SUBMSG);
subm = frame->m->submsgs[field->submsg_index];
@@ -290,7 +287,7 @@ static bool upb_decode_submsg(upb_decstate *d,
static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
uint64_t val;
void *field_mem;
@@ -335,7 +332,7 @@ static bool upb_decode_varintfield(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
void *field_mem;
uint64_t val;
@@ -359,7 +356,7 @@ static bool upb_decode_64bitfield(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_32bitfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
void *field_mem;
uint32_t val;
@@ -395,7 +392,7 @@ static bool upb_decode_fixedpacked(upb_array *arr, upb_stringview data,
static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
const char *field_start,
- const upb_msglayout_fieldinit_v1 *field,
+ const upb_msglayout_field *field,
upb_stringview val) {
upb_array *arr = upb_getorcreatearr(d, frame, field);
@@ -446,7 +443,7 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
case UPB_DESCRIPTOR_TYPE_SINT64:
VARINT_CASE(int64_t, upb_zzdecode_64);
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
- const upb_msglayout_msginit_v1 *subm;
+ const upb_msglayout *subm;
char *submsg;
void *field_mem;
@@ -477,7 +474,7 @@ static bool upb_decode_toarray(upb_decstate *d, upb_decframe *frame,
static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame,
const char *field_start,
- const upb_msglayout_fieldinit_v1 *field) {
+ const upb_msglayout_field *field) {
upb_stringview val;
CHK(upb_decode_string(&d->ptr, frame->limit, &val));
@@ -507,8 +504,8 @@ static bool upb_decode_delimitedfield(upb_decstate *d, upb_decframe *frame,
}
}
-static const upb_msglayout_fieldinit_v1 *upb_find_field(
- const upb_msglayout_msginit_v1 *l, uint32_t field_number) {
+static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
+ uint32_t field_number) {
/* Lots of optimization opportunities here. */
int i;
for (i = 0; i < l->field_count; i++) {
@@ -524,7 +521,7 @@ static bool upb_decode_field(upb_decstate *d, upb_decframe *frame) {
int field_number;
int wire_type;
const char *field_start = d->ptr;
- const upb_msglayout_fieldinit_v1 *field;
+ const upb_msglayout_field *field;
CHK(upb_decode_tag(&d->ptr, frame->limit, &field_number, &wire_type));
field = upb_find_field(frame->m, field_number);
@@ -576,7 +573,7 @@ static bool upb_skip_unknowngroup(upb_decstate *d, int field_number,
static bool upb_decode_message(upb_decstate *d, const char *limit,
int group_number, char *msg,
- const upb_msglayout_msginit_v1 *l) {
+ const upb_msglayout *l) {
upb_decframe frame;
frame.group_number = group_number;
frame.limit = limit;
@@ -590,8 +587,8 @@ static bool upb_decode_message(upb_decstate *d, const char *limit,
return true;
}
-bool upb_decode(upb_stringview buf, void *msg,
- const upb_msglayout_msginit_v1 *l, upb_env *env) {
+bool upb_decode(upb_stringview buf, void *msg, const upb_msglayout *l,
+ upb_env *env) {
upb_decstate state;
state.ptr = buf.data;
state.env = env;
diff --git a/upb/decode.h b/upb/decode.h
index 2a9e39e..963b399 100644
--- a/upb/decode.h
+++ b/upb/decode.h
@@ -9,8 +9,8 @@
UPB_BEGIN_EXTERN_C
-bool upb_decode(upb_stringview buf, void *msg,
- const upb_msglayout_msginit_v1 *l, upb_env *env);
+bool upb_decode(upb_stringview buf, void *msg, const upb_msglayout *l,
+ upb_env *env);
UPB_END_EXTERN_C
diff --git a/upb/encode.c b/upb/encode.c
index a017c46..24d72a8 100644
--- a/upb/encode.c
+++ b/upb/encode.c
@@ -126,15 +126,14 @@ 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_msginit_v1 *m,
+static uint32_t upb_readcase(const char *msg, const upb_msglayout *m,
int oneof_index) {
uint32_t ret;
memcpy(&ret, msg + m->oneofs[oneof_index].case_offset, sizeof(ret));
return ret;
}
-static bool upb_readhasbit(const char *msg,
- const upb_msglayout_fieldinit_v1 *f) {
+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));
}
@@ -150,12 +149,11 @@ static bool upb_put_fixedarray(upb_encstate *e, const upb_array *arr,
}
bool upb_encode_message(upb_encstate *e, const char *msg,
- const upb_msglayout_msginit_v1 *m,
- size_t *size);
+ const upb_msglayout *m, size_t *size);
static bool upb_encode_array(upb_encstate *e, const char *field_mem,
- const upb_msglayout_msginit_v1 *m,
- const upb_msglayout_fieldinit_v1 *f) {
+ const upb_msglayout *m,
+ const upb_msglayout_field *f) {
const upb_array *arr = *(const upb_array**)field_mem;
if (arr == NULL || arr->len == 0) {
@@ -221,7 +219,7 @@ do { ; } while(0)
case UPB_DESCRIPTOR_TYPE_GROUP: {
void **start = arr->data;
void **ptr = start + arr->len;
- const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index];
+ const upb_msglayout *subm = m->submsgs[f->submsg_index];
do {
size_t size;
ptr--;
@@ -234,7 +232,7 @@ do { ; } while(0)
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
void **start = arr->data;
void **ptr = start + arr->len;
- const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index];
+ const upb_msglayout *subm = m->submsgs[f->submsg_index];
do {
size_t size;
ptr--;
@@ -254,8 +252,8 @@ do { ; } while(0)
}
static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
- const upb_msglayout_msginit_v1 *m,
- const upb_msglayout_fieldinit_v1 *f,
+ 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;
@@ -305,8 +303,8 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
}
case UPB_DESCRIPTOR_TYPE_GROUP: {
size_t size;
- void *submsg = *(void**)field_mem;
- const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index];
+ void *submsg = *(void **)field_mem;
+ const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (skip_zero_value && submsg == NULL) {
return true;
}
@@ -316,8 +314,8 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
}
case UPB_DESCRIPTOR_TYPE_MESSAGE: {
size_t size;
- void *submsg = *(void**)field_mem;
- const upb_msglayout_msginit_v1 *subm = m->submsgs[f->submsg_index];
+ void *submsg = *(void **)field_mem;
+ const upb_msglayout *subm = m->submsgs[f->submsg_index];
if (skip_zero_value && submsg == NULL) {
return true;
}
@@ -330,9 +328,8 @@ static bool upb_encode_scalarfield(upb_encstate *e, const char *field_mem,
UPB_UNREACHABLE();
}
-bool upb_encode_hasscalarfield(const char *msg,
- const upb_msglayout_msginit_v1 *m,
- const upb_msglayout_fieldinit_v1 *f) {
+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) {
@@ -343,9 +340,8 @@ bool upb_encode_hasscalarfield(const char *msg,
}
}
-bool upb_encode_message(upb_encstate* e, const char *msg,
- const upb_msglayout_msginit_v1 *m,
- size_t *size) {
+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;
@@ -354,7 +350,7 @@ bool upb_encode_message(upb_encstate* e, const char *msg,
}
for (i = m->field_count - 1; i >= 0; i--) {
- const upb_msglayout_fieldinit_v1 *f = &m->fields[i];
+ const upb_msglayout_field *f = &m->fields[i];
if (f->label == UPB_LABEL_REPEATED) {
CHK(upb_encode_array(e, msg + f->offset, m, f));
@@ -363,7 +359,7 @@ bool upb_encode_message(upb_encstate* e, const char *msg,
if (f->oneof_index == UPB_NOT_IN_ONEOF) {
CHK(upb_encode_scalarfield(e, msg + f->offset, m, f, !m->is_proto2));
} else {
- const upb_msglayout_oneofinit_v1 *o = &m->oneofs[f->oneof_index];
+ const upb_msglayout_oneof *o = &m->oneofs[f->oneof_index];
CHK(upb_encode_scalarfield(e, msg + o->data_offset,
m, f, !m->is_proto2));
}
@@ -375,8 +371,8 @@ bool upb_encode_message(upb_encstate* e, const char *msg,
return true;
}
-char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *m,
- upb_env *env, size_t *size) {
+char *upb_encode(const void *msg, const upb_msglayout *m, upb_env *env,
+ size_t *size) {
upb_encstate e;
e.env = env;
e.buf = NULL;
diff --git a/upb/encode.h b/upb/encode.h
index 83908d4..8f42736 100644
--- a/upb/encode.h
+++ b/upb/encode.h
@@ -9,8 +9,8 @@
UPB_BEGIN_EXTERN_C
-char *upb_encode(const void *msg, const upb_msglayout_msginit_v1 *l,
- upb_env *env, size_t *size);
+char *upb_encode(const void *msg, const upb_msglayout *l, upb_env *env,
+ size_t *size);
UPB_END_EXTERN_C
diff --git a/upb/msg.c b/upb/msg.c
index 501e4c3..ca05779 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -2,20 +2,6 @@
#include "upb/msg.h"
#include "upb/structs.int.h"
-static bool is_power_of_two(size_t val) {
- return (val & (val - 1)) == 0;
-}
-
-/* Align up to the given power of 2. */
-static size_t align_up(size_t val, size_t align) {
- UPB_ASSERT(is_power_of_two(align));
- return (val + align - 1) & ~(align - 1);
-}
-
-static size_t div_round_up(size_t n, size_t d) {
- return (n + d - 1) / d;
-}
-
bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) {
return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 ||
type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 ||
@@ -70,7 +56,7 @@ static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
UPB_UNREACHABLE();
}
-static uint8_t upb_msg_fieldsize(const upb_msglayout_fieldinit_v1 *field) {
+static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) {
if (field->label == UPB_LABEL_REPEATED) {
return sizeof(void*);
} else {
@@ -78,14 +64,6 @@ static uint8_t upb_msg_fieldsize(const upb_msglayout_fieldinit_v1 *field) {
}
}
-static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
- if (upb_fielddef_isseq(f)) {
- return sizeof(void*);
- } else {
- return upb_msgval_sizeof(upb_fielddef_type(f));
- }
-}
-
/* TODO(haberman): this is broken right now because upb_msgval can contain
* a char* / size_t pair, which is too big for a upb_value. To fix this
* we'll probably need to dynamically allocate a upb_msgval and store a
@@ -121,292 +99,6 @@ static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
}
}
-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 *************************************************************/
-
-struct upb_msglayout {
- struct upb_msglayout_msginit_v1 data;
-};
-
-static void upb_msglayout_free(upb_msglayout *l) {
- upb_gfree(l->data.default_msg);
- upb_gfree(l);
-}
-
-static size_t upb_msglayout_place(upb_msglayout *l, size_t size) {
- size_t ret;
-
- l->data.size = align_up(l->data.size, size);
- ret = l->data.size;
- l->data.size += 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->data.size) {
- /* Allocate default message and set default values in it. */
- l->data.default_msg = upb_gmalloc(l->data.size);
- if (!l->data.default_msg) {
- return false;
- }
-
- memset(l->data.default_msg, 0, l->data.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->data.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) {
- upb_msg_field_iter it;
- upb_msg_oneof_iter oit;
- size_t hasbit;
- size_t submsg_count = 0;
- const upb_msglayout_msginit_v1 **submsgs;
- upb_msglayout_fieldinit_v1 *fields;
- upb_msglayout_oneofinit_v1 *oneofs;
-
- 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_issubmsg(f)) {
- submsg_count++;
- }
- }
-
- memset(l, 0, sizeof(*l));
-
- 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))) {
- /* OOM. */
- upb_gfree(fields);
- upb_gfree(submsgs);
- upb_gfree(oneofs);
- return false;
- }
-
- l->data.field_count = upb_msgdef_numfields(m);
- l->data.oneof_count = upb_msgdef_numoneofs(m);
- l->data.fields = fields;
- l->data.submsgs = submsgs;
- l->data.oneofs = oneofs;
- l->data.is_proto2 = (upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2);
-
- /* Allocate data offsets in three stages:
- *
- * 1. hasbits.
- * 2. regular fields.
- * 3. oneof fields.
- *
- * OPT: There is a lot of room for optimization here to minimize the size.
- */
-
- /* Allocate hasbits and set basic field attributes. */
- submsg_count = 0;
- for (upb_msg_field_begin(&it, m), hasbit = 0;
- !upb_msg_field_done(&it);
- upb_msg_field_next(&it)) {
- const upb_fielddef* f = upb_msg_iter_field(&it);
- upb_msglayout_fieldinit_v1 *field = &fields[upb_fielddef_index(f)];
-
- field->number = upb_fielddef_number(f);
- 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->data;
- } else {
- field->submsg_index = UPB_NO_SUBMSG;
- }
-
- if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) {
- field->hasbit = hasbit++;
- } else {
- field->hasbit = UPB_NO_HASBIT;
- }
- }
-
- /* Account for space used by hasbits. */
- l->data.size = div_round_up(hasbit, 8);
-
- /* Allocate non-oneof fields. */
- 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);
- size_t field_size = upb_msg_fielddefsize(f);
- size_t index = upb_fielddef_index(f);
-
- if (upb_fielddef_containingoneof(f)) {
- /* Oneofs are handled separately below. */
- continue;
- }
-
- fields[index].offset = upb_msglayout_place(l, field_size);
- }
-
- /* Allocate oneof fields. Each oneof field consists of a uint32 for the case
- * and space for the actual data. */
- for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
- upb_msg_oneof_next(&oit)) {
- const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
- upb_oneof_iter fit;
-
- size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */
- upb_msglayout_oneofinit_v1 *oneof = &oneofs[upb_oneofdef_index(o)];
- size_t field_size = 0;
-
- /* Calculate field size: the max of all field sizes. */
- for (upb_oneof_begin(&fit, o);
- !upb_oneof_done(&fit);
- upb_oneof_next(&fit)) {
- const upb_fielddef* f = upb_oneof_iter_field(&fit);
- field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
- }
-
- /* Align and allocate case offset. */
- oneof->case_offset = upb_msglayout_place(l, case_size);
- oneof->data_offset = upb_msglayout_place(l, field_size);
- }
-
- /* Size of the entire structure should be a multiple of its greatest
- * alignment. TODO: track overall alignment for real? */
- l->data.size = align_up(l->data.size, 8);
-
- return upb_msglayout_initdefault(l, m);
-}
-
-
-/** upb_msgfactory ************************************************************/
-
-struct upb_msgfactory {
- const upb_symtab *symtab; /* We own a ref. */
- upb_inttable layouts;
- upb_inttable mergehandlers;
-};
-
-upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) {
- upb_msgfactory *ret = upb_gmalloc(sizeof(*ret));
-
- ret->symtab = symtab;
- upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR);
- upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR);
-
- return ret;
-}
-
-void upb_msgfactory_free(upb_msgfactory *f) {
- upb_inttable_iter i;
- upb_inttable_begin(&i, &f->layouts);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i));
- upb_msglayout_free(l);
- }
-
- upb_inttable_begin(&i, &f->mergehandlers);
- for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
- const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i));
- upb_handlers_unref(h, f);
- }
-
- upb_inttable_uninit(&f->layouts);
- upb_inttable_uninit(&f->mergehandlers);
- upb_gfree(f);
-}
-
-const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) {
- return f->symtab;
-}
-
-const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
- const upb_msgdef *m) {
- upb_value v;
- UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m);
- UPB_ASSERT(!upb_msgdef_mapentry(m));
-
- if (upb_inttable_lookupptr(&f->layouts, m, &v)) {
- UPB_ASSERT(upb_value_getptr(v));
- return upb_value_getptr(v);
- } else {
- /* In case of circular dependency, layout has to be inserted first. */
- upb_msglayout *l = upb_gmalloc(sizeof(*l));
- upb_msgfactory *mutable_f = (void*)f;
- upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l));
- UPB_ASSERT(l);
- if (!upb_msglayout_init(m, l, f)) {
- upb_msglayout_free(l);
- }
- return l;
- }
-}
-
/** upb_msg *******************************************************************/
@@ -432,7 +124,7 @@ typedef struct {
} upb_msg_internal_withext;
static int upb_msg_internalsize(const upb_msglayout *l) {
- return sizeof(upb_msg_internal) - l->data.extendable * sizeof(void*);
+ return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
}
static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
@@ -445,29 +137,29 @@ static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
static upb_msg_internal_withext *upb_msg_getinternalwithext(
upb_msg *msg, const upb_msglayout *l) {
- UPB_ASSERT(l->data.extendable);
+ UPB_ASSERT(l->extendable);
return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext));
}
-static const upb_msglayout_fieldinit_v1 *upb_msg_checkfield(
- int field_index, const upb_msglayout *l) {
- UPB_ASSERT(field_index >= 0 && field_index < l->data.field_count);
- return &l->data.fields[field_index];
+static const upb_msglayout_field *upb_msg_checkfield(int field_index,
+ const upb_msglayout *l) {
+ UPB_ASSERT(field_index >= 0 && field_index < l->field_count);
+ return &l->fields[field_index];
}
-static bool upb_msg_inoneof(const upb_msglayout_fieldinit_v1 *field) {
+static bool upb_msg_inoneof(const upb_msglayout_field *field) {
return field->oneof_index != UPB_NOT_IN_ONEOF;
}
static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
const upb_msglayout *l) {
- const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l);
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
UPB_ASSERT(upb_msg_inoneof(field));
- return PTR_AT(msg, l->data.oneofs[field->oneof_index].case_offset, uint32_t);
+ return PTR_AT(msg, l->oneofs[field->oneof_index].case_offset, uint32_t);
}
static size_t upb_msg_sizeof(const upb_msglayout *l) {
- return l->data.size + upb_msg_internalsize(l);
+ return l->size + upb_msg_internalsize(l);
}
upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) {
@@ -482,16 +174,16 @@ 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->data.default_msg) {
- memcpy(msg, l->data.default_msg, l->data.size);
+ if (l->default_msg) {
+ memcpy(msg, l->default_msg, l->size);
} else {
- memset(msg, 0, l->data.size);
+ memset(msg, 0, l->size);
}
/* Initialize internal members. */
upb_msg_getinternal(msg)->arena = a;
- if (l->data.extendable) {
+ if (l->extendable) {
upb_msg_getinternalwithext(msg, l)->extdict = NULL;
}
@@ -505,32 +197,32 @@ upb_arena *upb_msg_arena(const upb_msg *msg) {
bool upb_msg_has(const upb_msg *msg,
int field_index,
const upb_msglayout *l) {
- const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, l);
+ const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
- UPB_ASSERT(l->data.is_proto2);
+ UPB_ASSERT(l->is_proto2);
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->data.fields[field_index].hasbit;
+ uint32_t hasbit = l->fields[field_index].hasbit;
return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
}
}
upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
const upb_msglayout *l) {
- const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, 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->data.oneofs[field->oneof_index].data_offset;
+ 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->data.default_msg, field->offset, size);
+ return upb_msgval_read(l->default_msg, field->offset, size);
}
} else {
return upb_msgval_read(msg, field->offset, size);
@@ -539,11 +231,11 @@ upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val,
const upb_msglayout *l) {
- const upb_msglayout_fieldinit_v1 *field = upb_msg_checkfield(field_index, 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->data.oneofs[field->oneof_index].data_offset;
+ 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 {
diff --git a/upb/msg.h b/upb/msg.h
index 5472d17..557a1f4 100644
--- a/upb/msg.h
+++ b/upb/msg.h
@@ -31,21 +31,14 @@ namespace upb {
class Array;
class Map;
class MapIterator;
-class MessageFactory;
class MessageLayout;
-class Visitor;
-class VisitorPlan;
}
#endif
-UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory)
-UPB_DECLARE_TYPE(upb::MessageLayout, upb_msglayout)
UPB_DECLARE_TYPE(upb::Array, upb_array)
UPB_DECLARE_TYPE(upb::Map, upb_map)
UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter)
-UPB_DECLARE_TYPE(upb::Visitor, upb_visitor)
-UPB_DECLARE_TYPE(upb::VisitorPlan, upb_visitorplan)
/* TODO(haberman): C++ accessors */
@@ -56,39 +49,45 @@ typedef void upb_msg;
/** upb_msglayout *************************************************************/
-/* upb_msglayout represents the memory layout of a given upb_msgdef. You get
- * instances of this from a upb_msgfactory, and the factory always owns the
- * msglayout. */
+/* upb_msglayout represents the memory layout of a given upb_msgdef. The
+ * 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
-/** upb_msgfactory ************************************************************/
-
-/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and
- * upb_visitorplan objects. These are the objects necessary to represent,
- * populate, and and visit upb_msg objects.
- *
- * These caches are all populated by upb_msgdef, and lazily created on demand.
- */
+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. */
+ uint8_t descriptortype;
+ uint8_t label;
+} upb_msglayout_field;
-/* Creates and destroys a msgfactory, respectively. The messages for this
- * msgfactory must come from |symtab| (which should outlive the msgfactory). */
-upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab);
-void upb_msgfactory_free(upb_msgfactory *f);
+typedef struct {
+ uint32_t data_offset;
+ uint32_t case_offset;
+} upb_msglayout_oneof;
-const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f);
+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 field_count;
+ uint16_t oneof_count;
+ bool extendable;
+ bool is_proto2;
+} upb_msglayout;
-/* The functions to get cached objects, lazily creating them on demand. These
- * all require:
- *
- * - m is in upb_msgfactory_symtab(f)
- * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts).
- *
- * The returned objects will live for as long as the msgfactory does.
- *
- * TODO(haberman): consider making this thread-safe and take a const
- * upb_msgfactory. */
-const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
- const upb_msgdef *m);
+#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 ************************************************************/
@@ -291,52 +290,6 @@ upb_msgval upb_mapiter_value(const upb_mapiter *i);
void upb_mapiter_setdone(upb_mapiter *i);
bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2);
-
-/** Interfaces for generated code *********************************************/
-
-#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. */
- uint8_t descriptortype;
- uint8_t label;
-} upb_msglayout_fieldinit_v1;
-
-typedef struct {
- uint32_t data_offset;
- uint32_t case_offset;
-} upb_msglayout_oneofinit_v1;
-
-typedef struct upb_msglayout_msginit_v1 {
- const struct upb_msglayout_msginit_v1 *const* submsgs;
- const upb_msglayout_fieldinit_v1 *fields;
- const upb_msglayout_oneofinit_v1 *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 field_count;
- uint16_t oneof_count;
- bool extendable;
- bool is_proto2;
-} upb_msglayout_msginit_v1;
-
-#define UPB_ALIGN_UP_TO(val, align) ((val + (align - 1)) & -align)
-#define UPB_ALIGNED_SIZEOF(type) UPB_ALIGN_UP_TO(sizeof(type), sizeof(void*))
-
-/* Initialize/uninitialize a msglayout from a msginit. If upb uses v1
- * internally, this will not allocate any memory. Should only be used by
- * generated code. */
-upb_msglayout *upb_msglayout_frominit_v1(
- const upb_msglayout_msginit_v1 *init, upb_alloc *a);
-void upb_msglayout_uninit_v1(upb_msglayout *layout, upb_alloc *a);
-
UPB_END_EXTERN_C
#endif /* UPB_MSG_H_ */
diff --git a/upb/msgfactory.c b/upb/msgfactory.c
new file mode 100644
index 0000000..b544967
--- /dev/null
+++ b/upb/msgfactory.c
@@ -0,0 +1,325 @@
+
+#include "upb/msgfactory.h"
+
+static bool is_power_of_two(size_t val) {
+ return (val & (val - 1)) == 0;
+}
+
+/* Align up to the given power of 2. */
+static size_t align_up(size_t val, size_t align) {
+ UPB_ASSERT(is_power_of_two(align));
+ return (val + align - 1) & ~(align - 1);
+}
+
+static size_t div_round_up(size_t n, size_t d) {
+ return (n + d - 1) / d;
+}
+
+static size_t upb_msgval_sizeof2(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_DOUBLE:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ return 8;
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_FLOAT:
+ return 4;
+ case UPB_TYPE_BOOL:
+ return 1;
+ case UPB_TYPE_MESSAGE:
+ return sizeof(void*);
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_STRING:
+ return sizeof(upb_stringview);
+ }
+ UPB_UNREACHABLE();
+}
+
+static uint8_t upb_msg_fielddefsize(const upb_fielddef *f) {
+ if (upb_fielddef_isseq(f)) {
+ return sizeof(void*);
+ } else {
+ return upb_msgval_sizeof2(upb_fielddef_type(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);
+}
+
+static size_t upb_msglayout_place(upb_msglayout *l, size_t size) {
+ size_t ret;
+
+ l->size = align_up(l->size, size);
+ ret = l->size;
+ l->size += 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) {
+ upb_msg_field_iter it;
+ upb_msg_oneof_iter oit;
+ size_t hasbit;
+ 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);
+ upb_msg_field_next(&it)) {
+ const upb_fielddef* f = upb_msg_iter_field(&it);
+ if (upb_fielddef_issubmsg(f)) {
+ submsg_count++;
+ }
+ }
+
+ memset(l, 0, sizeof(*l));
+
+ 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))) {
+ /* 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:
+ *
+ * 1. hasbits.
+ * 2. regular fields.
+ * 3. oneof fields.
+ *
+ * OPT: There is a lot of room for optimization here to minimize the size.
+ */
+
+ /* Allocate hasbits and set basic field attributes. */
+ submsg_count = 0;
+ for (upb_msg_field_begin(&it, m), hasbit = 0;
+ !upb_msg_field_done(&it);
+ upb_msg_field_next(&it)) {
+ const upb_fielddef* f = upb_msg_iter_field(&it);
+ upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
+
+ field->number = upb_fielddef_number(f);
+ 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++;
+ } else {
+ field->hasbit = UPB_NO_HASBIT;
+ }
+ }
+
+ /* Account for space used by hasbits. */
+ l->size = div_round_up(hasbit, 8);
+
+ /* Allocate non-oneof fields. */
+ 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);
+ size_t field_size = upb_msg_fielddefsize(f);
+ size_t index = upb_fielddef_index(f);
+
+ if (upb_fielddef_containingoneof(f)) {
+ /* Oneofs are handled separately below. */
+ continue;
+ }
+
+ fields[index].offset = upb_msglayout_place(l, field_size);
+ }
+
+ /* Allocate oneof fields. Each oneof field consists of a uint32 for the case
+ * and space for the actual data. */
+ for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit);
+ upb_msg_oneof_next(&oit)) {
+ const upb_oneofdef* o = upb_msg_iter_oneof(&oit);
+ 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;
+
+ /* Calculate field size: the max of all field sizes. */
+ for (upb_oneof_begin(&fit, o);
+ !upb_oneof_done(&fit);
+ upb_oneof_next(&fit)) {
+ const upb_fielddef* f = upb_oneof_iter_field(&fit);
+ field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
+ }
+
+ /* Align and allocate case offset. */
+ oneof->case_offset = upb_msglayout_place(l, case_size);
+ oneof->data_offset = upb_msglayout_place(l, field_size);
+ }
+
+ /* 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);
+}
+
+
+/** upb_msgfactory ************************************************************/
+
+struct upb_msgfactory {
+ const upb_symtab *symtab; /* We own a ref. */
+ upb_inttable layouts;
+ upb_inttable mergehandlers;
+};
+
+upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) {
+ upb_msgfactory *ret = upb_gmalloc(sizeof(*ret));
+
+ ret->symtab = symtab;
+ upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR);
+ upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR);
+
+ return ret;
+}
+
+void upb_msgfactory_free(upb_msgfactory *f) {
+ upb_inttable_iter i;
+ upb_inttable_begin(&i, &f->layouts);
+ for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ upb_msglayout *l = upb_value_getptr(upb_inttable_iter_value(&i));
+ upb_msglayout_free(l);
+ }
+
+ upb_inttable_begin(&i, &f->mergehandlers);
+ for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
+ const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i));
+ upb_handlers_unref(h, f);
+ }
+
+ upb_inttable_uninit(&f->layouts);
+ upb_inttable_uninit(&f->mergehandlers);
+ upb_gfree(f);
+}
+
+const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f) {
+ return f->symtab;
+}
+
+const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
+ const upb_msgdef *m) {
+ upb_value v;
+ UPB_ASSERT(upb_symtab_lookupmsg(f->symtab, upb_msgdef_fullname(m)) == m);
+ UPB_ASSERT(!upb_msgdef_mapentry(m));
+
+ if (upb_inttable_lookupptr(&f->layouts, m, &v)) {
+ UPB_ASSERT(upb_value_getptr(v));
+ return upb_value_getptr(v);
+ } else {
+ /* In case of circular dependency, layout has to be inserted first. */
+ upb_msglayout *l = upb_gmalloc(sizeof(*l));
+ upb_msgfactory *mutable_f = (void*)f;
+ upb_inttable_insertptr(&mutable_f->layouts, m, upb_value_ptr(l));
+ UPB_ASSERT(l);
+ if (!upb_msglayout_init(m, l, f)) {
+ upb_msglayout_free(l);
+ }
+ return l;
+ }
+}
diff --git a/upb/msgfactory.h b/upb/msgfactory.h
new file mode 100644
index 0000000..73a26ba
--- /dev/null
+++ b/upb/msgfactory.h
@@ -0,0 +1,40 @@
+
+#include "upb/def.h"
+#include "upb/msg.h"
+
+#ifndef UPB_MSGFACTORY_H_
+#define UPB_MSGFACTORY_H_
+
+UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory)
+
+/** upb_msgfactory ************************************************************/
+
+/* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and
+ * upb_visitorplan objects. These are the objects necessary to represent,
+ * populate, and and visit upb_msg objects.
+ *
+ * These caches are all populated by upb_msgdef, and lazily created on demand.
+ */
+
+/* Creates and destroys a msgfactory, respectively. The messages for this
+ * msgfactory must come from |symtab| (which should outlive the msgfactory). */
+upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab);
+void upb_msgfactory_free(upb_msgfactory *f);
+
+const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f);
+
+/* The functions to get cached objects, lazily creating them on demand. These
+ * all require:
+ *
+ * - m is in upb_msgfactory_symtab(f)
+ * - upb_msgdef_mapentry(m) == false (since map messages can't have layouts).
+ *
+ * The returned objects will live for as long as the msgfactory does.
+ *
+ * TODO(haberman): consider making this thread-safe and take a const
+ * upb_msgfactory. */
+const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f,
+ const upb_msgdef *m);
+
+
+#endif /* UPB_MSGFACTORY_H_ */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback