summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2011-05-10 21:59:46 -0700
committerJoshua Haberman <jhaberman@gmail.com>2011-05-10 21:59:46 -0700
commit3231fd0fdd64bc6355bce921a988713524726f23 (patch)
tree326d6c6d334d14005db80c448fca485f641ed516
parentea2a80840e08887e6e5ea59bce1f56a3c69bd38c (diff)
Vastly improved/simplified the upb_handlers API.
-rw-r--r--benchmarks/parsestream.upb_table.c5
-rw-r--r--benchmarks/parsetostruct.upb_table.c4
-rw-r--r--src/upb_decoder.c2
-rw-r--r--src/upb_def.c204
-rw-r--r--src/upb_def.h3
-rw-r--r--src/upb_glue.c10
-rw-r--r--src/upb_handlers.c277
-rw-r--r--src/upb_handlers.h204
-rw-r--r--src/upb_msg.c90
-rw-r--r--src/upb_msg.h6
-rw-r--r--src/upb_textprinter.c7
-rw-r--r--src/upb_textprinter.h2
-rw-r--r--tests/tests.c5
13 files changed, 378 insertions, 441 deletions
diff --git a/benchmarks/parsestream.upb_table.c b/benchmarks/parsestream.upb_table.c
index 6107894..00eb1bb 100644
--- a/benchmarks/parsestream.upb_table.c
+++ b/benchmarks/parsestream.upb_table.c
@@ -61,9 +61,10 @@ static bool initialize()
return false;
}
- upb_handlers_init(&handlers, def);
+ upb_handlers_init(&handlers);
// Cause all messages to be read, but do nothing when they are.
- upb_register_all(&handlers, NULL, NULL, value, startsubmsg, NULL);
+ upb_handlerset hset = {NULL, NULL, value, startsubmsg, NULL};
+ upb_handlers_reghandlerset(&handlers, def, &hset);
upb_decoder_init(&decoder, &handlers);
upb_stringsrc_init(&stringsrc);
return true;
diff --git a/benchmarks/parsetostruct.upb_table.c b/benchmarks/parsetostruct.upb_table.c
index 397f964..10d1481 100644
--- a/benchmarks/parsetostruct.upb_table.c
+++ b/benchmarks/parsetostruct.upb_table.c
@@ -53,8 +53,8 @@ static bool initialize()
msg = upb_msg_new(def);
upb_stringsrc_init(&strsrc);
- upb_handlers_init(&h, def);
- upb_msg_regdhandlers(&h);
+ upb_handlers_init(&h);
+ upb_msg_reghandlers(&h, def);
upb_decoder_init(&d, &h);
if (!BYREF) {
diff --git a/src/upb_decoder.c b/src/upb_decoder.c
index 0087b86..24cfd64 100644
--- a/src/upb_decoder.c
+++ b/src/upb_decoder.c
@@ -341,7 +341,7 @@ void upb_decoder_init(upb_decoder *d, upb_handlers *handlers) {
// Set function pointers for each field's decode function.
for (int i = 0; i < handlers->msgs_len; i++) {
- upb_mhandlers *m = &handlers->msgs[i];
+ upb_mhandlers *m = handlers->msgs[i];
for(upb_inttable_iter i = upb_inttable_begin(&m->fieldtab); !upb_inttable_done(i);
i = upb_inttable_next(&m->fieldtab, i)) {
upb_fhandlers *f = upb_inttable_iter_value(i);
diff --git a/src/upb_def.c b/src/upb_def.c
index 338bd3d..d87c7e9 100644
--- a/src/upb_def.c
+++ b/src/upb_def.c
@@ -264,8 +264,8 @@ struct _upb_defbuilder {
};
// Forward declares for top-level file descriptors.
-static void upb_msgdef_register_DescriptorProto(upb_handlers *h);
-static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h);
+static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h);
+static upb_mhandlers * upb_enumdef_register_EnumDescriptorProto(upb_handlers *h);
upb_defbuilder *upb_defbuilder_new(upb_symtab *s) {
upb_defbuilder *b = malloc(sizeof(*b));
@@ -344,28 +344,27 @@ static upb_flow_t upb_defbuilder_FileDescriptorProto_package(void *_b,
return UPB_CONTINUE;
}
-static void upb_defbuilder_register_FileDescriptorProto(upb_handlers *h) {
- upb_register_startend(h, upb_defbuilder_FileDescriptorProto_startmsg,
- upb_defbuilder_FileDescriptorProto_endmsg);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDNUM,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE__FIELDTYPE, false,
- &upb_defbuilder_FileDescriptorProto_package, UPB_NO_VALUE);
+static upb_mhandlers *upb_defbuilder_register_FileDescriptorProto(
+ upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setstartmsg(m, &upb_defbuilder_FileDescriptorProto_startmsg);
+ upb_mhandlers_setendmsg(m, &upb_defbuilder_FileDescriptorProto_endmsg);
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDNUM,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE__FIELDTYPE, true);
- upb_msgdef_register_DescriptorProto(h);
- upb_handlers_typed_pop(h);
+#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDNUM
+#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDTYPE
+ upb_fhandlers *f =
+ upb_mhandlers_newfield(m, FNUM(PACKAGE), FTYPE(PACKAGE), false);
+ upb_fhandlers_setvalue(f, &upb_defbuilder_FileDescriptorProto_package);
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDNUM,
- GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE, true);
- upb_enumdef_register_EnumDescriptorProto(h);
- upb_handlers_typed_pop(h);
-
- // TODO: services and extensions.
+ upb_mhandlers_newsubmsgfield(m, FNUM(MESSAGE_TYPE), FTYPE(MESSAGE_TYPE), true,
+ upb_msgdef_register_DescriptorProto(h));
+ upb_mhandlers_newsubmsgfield(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true,
+ upb_enumdef_register_EnumDescriptorProto(h));
+ // TODO: services, extensions
+ return m;
}
+#undef FNUM
+#undef FTYPE
// Handlers for google.protobuf.FileDescriptorSet.
static bool upb_symtab_add_defs(upb_symtab *s, upb_def **defs, int num_defs,
@@ -379,17 +378,22 @@ static void upb_defbuilder_FileDescriptorSet_onendmsg(void *_b,
upb_defbuilder_free(b);
}
-static void upb_defbuilder_register_FileDescriptorSet(upb_handlers *h) {
- upb_register_startend(h, NULL, upb_defbuilder_FileDescriptorSet_onendmsg);
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDNUM,
- GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE__FIELDTYPE, true);
- upb_defbuilder_register_FileDescriptorProto(h);
- upb_handlers_typed_pop(h);
+static upb_mhandlers *upb_defbuilder_register_FileDescriptorSet(upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setendmsg(m, upb_defbuilder_FileDescriptorSet_onendmsg);
+
+#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDNUM
+#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDTYPE
+ upb_mhandlers_newsubmsgfield(m, FNUM(FILE), FTYPE(FILE), true,
+ upb_defbuilder_register_FileDescriptorProto(h));
+ return m;
}
-void upb_defbuilder_reghandlers(upb_handlers *h) {
- upb_defbuilder_register_FileDescriptorSet(h);
+#undef FNUM
+#undef FTYPE
+
+upb_mhandlers *upb_defbuilder_reghandlers(upb_handlers *h) {
h->should_jit = false;
+ return upb_defbuilder_register_FileDescriptorSet(h);
}
@@ -488,18 +492,24 @@ static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b,
b->name = NULL;
}
-static void upb_enumdef_register_EnumValueDescriptorProto(upb_handlers *h) {
- upb_register_startend(h, upb_enumdef_EnumValueDescriptorProto_startmsg,
- upb_enumdef_EnumValueDescriptorProto_endmsg);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDNUM,
- GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME__FIELDTYPE, false,
- &upb_enumdef_EnumValueDescriptorProto_name, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDNUM,
- GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER__FIELDTYPE, false,
- &upb_enumdef_EnumValueDescriptorProto_number, UPB_NO_VALUE);
+static upb_mhandlers *upb_enumdef_register_EnumValueDescriptorProto(
+ upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumValueDescriptorProto_startmsg);
+ upb_mhandlers_setendmsg(m, &upb_enumdef_EnumValueDescriptorProto_endmsg);
+
+#define FNUM(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDNUM
+#define FTYPE(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDTYPE
+ upb_fhandlers *f;
+ f = upb_mhandlers_newfield(m, FNUM(NAME), FTYPE(NAME), false);
+ upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_name);
+
+ f = upb_mhandlers_newfield(m, FNUM(NUMBER), FTYPE(NUMBER), false);
+ upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_number);
+ return m;
}
+#undef FNUM
+#undef FTYPE
// google.protobuf.EnumDescriptorProto.
static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_b) {
@@ -536,20 +546,22 @@ static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_b,
return UPB_CONTINUE;
}
-static void upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) {
- upb_register_startend(h, &upb_enumdef_EnumDescriptorProto_startmsg,
- &upb_enumdef_EnumDescriptorProto_endmsg);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDNUM,
- GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME__FIELDTYPE, false,
- &upb_enumdef_EnumDescriptorProto_name, UPB_NO_VALUE);
+static upb_mhandlers *upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumDescriptorProto_startmsg);
+ upb_mhandlers_setendmsg(m, &upb_enumdef_EnumDescriptorProto_endmsg);
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDNUM,
- GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE__FIELDTYPE, true);
- upb_enumdef_register_EnumValueDescriptorProto(h);
- upb_handlers_typed_pop(h);
+#define FNUM(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDNUM
+#define FTYPE(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDTYPE
+ upb_fhandlers *f = upb_mhandlers_newfield(m, FNUM(NAME), FTYPE(NAME), false);
+ upb_fhandlers_setvalue(f, &upb_enumdef_EnumDescriptorProto_name);
+
+ upb_mhandlers_newsubmsgfield(m, FNUM(VALUE), FTYPE(VALUE), true,
+ upb_enumdef_register_EnumValueDescriptorProto(h));
+ return m;
}
+#undef FNUM
+#undef FTYPE
upb_enum_iter upb_enum_begin(upb_enumdef *e) {
// We could iterate over either table here; the choice is arbitrary.
@@ -810,33 +822,29 @@ static upb_flow_t upb_fielddef_ondefaultval(void *_b, upb_value fval,
return UPB_CONTINUE;
}
-static void upb_fielddef_register_FieldDescriptorProto(upb_handlers *h) {
- upb_register_startend(h, upb_fielddef_startmsg, upb_fielddef_endmsg);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE__FIELDTYPE, false,
- &upb_fielddef_ontype, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL__FIELDTYPE, false,
- &upb_fielddef_onlabel, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER__FIELDTYPE, false,
- &upb_fielddef_onnumber, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME__FIELDTYPE, false,
- &upb_fielddef_onname, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME__FIELDTYPE, false,
- &upb_fielddef_ontypename, UPB_NO_VALUE);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDNUM,
- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE__FIELDTYPE, false,
- &upb_fielddef_ondefaultval, UPB_NO_VALUE);
+static upb_mhandlers *upb_fielddef_register_FieldDescriptorProto(
+ upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setstartmsg(m, &upb_fielddef_startmsg);
+ upb_mhandlers_setendmsg(m, &upb_fielddef_endmsg);
+
+#define FIELD(name, handler) \
+ upb_fhandlers_setvalue( \
+ upb_mhandlers_newfield(m, \
+ GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDNUM, \
+ GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDTYPE, \
+ false), \
+ handler);
+ FIELD(TYPE, &upb_fielddef_ontype);
+ FIELD(LABEL, &upb_fielddef_onlabel);
+ FIELD(NUMBER, &upb_fielddef_onnumber);
+ FIELD(NAME, &upb_fielddef_onname);
+ FIELD(TYPE_NAME, &upb_fielddef_ontypename);
+ FIELD(DEFAULT_VALUE, &upb_fielddef_ondefaultval);
+ return m;
}
+#undef FNUM
+#undef FTYPE
/* upb_msgdef *****************************************************************/
@@ -951,32 +959,30 @@ static upb_flow_t upb_msgdef_onname(void *_b, upb_value fval, upb_value val) {
return UPB_CONTINUE;
}
-static void upb_msgdef_register_DescriptorProto(upb_handlers *h) {
- upb_register_startend(h, &upb_msgdef_startmsg, &upb_msgdef_endmsg);
- upb_register_typed_value(h,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDNUM,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME__FIELDTYPE, false,
- &upb_msgdef_onname, UPB_NO_VALUE);
+static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h) {
+ upb_mhandlers *m = upb_handlers_newmsg(h);
+ upb_mhandlers_setstartmsg(m, &upb_msgdef_startmsg);
+ upb_mhandlers_setendmsg(m, &upb_msgdef_endmsg);
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDNUM,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD__FIELDTYPE, true);
- upb_fielddef_register_FieldDescriptorProto(h);
- upb_handlers_typed_pop(h);
+#define FNUM(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDNUM
+#define FTYPE(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDTYPE
+ upb_fhandlers *f = upb_mhandlers_newfield(m, FNUM(NAME), FTYPE(NAME), false);
+ upb_fhandlers_setvalue(f, &upb_msgdef_onname);
- // DescriptorProto is self-recursive, so we must link the definition.
- upb_handlers_typed_link(h,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDNUM,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE__FIELDTYPE, true, 0);
+ upb_mhandlers_newsubmsgfield(m, FNUM(FIELD), FTYPE(FIELD), true,
+ upb_fielddef_register_FieldDescriptorProto(h));
+ upb_mhandlers_newsubmsgfield(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true,
+ upb_enumdef_register_EnumDescriptorProto(h));
- upb_handlers_typed_push(h,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDNUM,
- GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE__FIELDTYPE, true);
- upb_enumdef_register_EnumDescriptorProto(h);
- upb_handlers_typed_pop(h);
+ // DescriptorProto is self-recursive, so we must link the definition.
+ upb_mhandlers_newsubmsgfield(
+ m, FNUM(NESTED_TYPE), FTYPE(NESTED_TYPE), true, m);
// TODO: extensions.
+ return m;
}
+#undef FNUM
+#undef FTYPE
static void upb_msgdef_free(upb_msgdef *m)
{
diff --git a/src/upb_def.h b/src/upb_def.h
index ba1c410..d02fbf4 100644
--- a/src/upb_def.h
+++ b/src/upb_def.h
@@ -328,6 +328,7 @@ upb_def **upb_symtab_getdefs(upb_symtab *s, int *count, upb_deftype_t type);
struct _upb_defbuilder;
typedef struct _upb_defbuilder upb_defbuilder;
struct _upb_handlers;
+struct _upb_handlers;
// Allocates a new defbuilder that will add defs to the given symtab.
upb_defbuilder *upb_defbuilder_new(upb_symtab *s);
@@ -337,7 +338,7 @@ upb_defbuilder *upb_defbuilder_new(upb_symtab *s);
//
// TODO: should this allow redefinition? Either is possible, but which is
// more useful? Maybe it should be an option.
-void upb_defbuilder_reghandlers(struct _upb_handlers *h);
+struct _upb_mhandlers *upb_defbuilder_reghandlers(struct _upb_handlers *h);
/* upb_def casts **************************************************************/
diff --git a/src/upb_glue.c b/src/upb_glue.c
index b6a0273..d54b446 100644
--- a/src/upb_glue.c
+++ b/src/upb_glue.c
@@ -18,8 +18,8 @@ void upb_strtomsg(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_stringsrc_reset(&strsrc, str);
upb_handlers h;
- upb_handlers_init(&h, md);
- upb_msg_regdhandlers(&h);
+ upb_handlers_init(&h);
+ upb_msg_reghandlers(&h, md);
upb_decoder d;
upb_decoder_init(&d, &h);
@@ -39,8 +39,8 @@ void upb_msgtotext(upb_string *str, upb_msg *msg, upb_msgdef *md,
upb_textprinter *p = upb_textprinter_new();
upb_handlers h;
- upb_handlers_init(&h, md);
- upb_textprinter_reghandlers(&h);
+ upb_handlers_init(&h);
+ upb_textprinter_reghandlers(&h, md);
upb_textprinter_reset(p, upb_stringsink_bytesink(&strsink), single_line);
upb_status status = UPB_STATUS_INIT;
@@ -60,7 +60,7 @@ void upb_parsedesc(upb_symtab *symtab, upb_string *str, upb_status *status) {
upb_stringsrc_reset(&strsrc, str);
upb_handlers h;
- upb_handlers_init(&h, NULL);
+ upb_handlers_init(&h);
upb_defbuilder_reghandlers(&h);
upb_decoder d;
diff --git a/src/upb_handlers.c b/src/upb_handlers.c
index 25448da..5f97649 100644
--- a/src/upb_handlers.c
+++ b/src/upb_handlers.c
@@ -9,8 +9,6 @@
#include "upb_handlers.h"
-/* upb_handlers ***************************************************************/
-
upb_flow_t upb_startmsg_nop(void *closure) {
(void)closure;
return UPB_CONTINUE;
@@ -39,220 +37,162 @@ upb_flow_t upb_endsubmsg_nop(void *closure, upb_value fval) {
return UPB_CONTINUE;
}
-upb_flow_t upb_unknownval_nop(void *closure, upb_field_number_t fieldnum,
- upb_value val) {
- (void)closure;
- (void)fieldnum;
- (void)val;
- return UPB_CONTINUE;
-}
-
-static void upb_msgent_init(upb_mhandlers *e) {
- upb_inttable_init(&e->fieldtab, 8, sizeof(upb_fhandlers));
- e->startmsg = &upb_startmsg_nop;
- e->endmsg = &upb_endmsg_nop;
- e->tablearray = NULL;
- e->is_group = false;
-}
-
-void upb_handlers_init(upb_handlers *h, upb_msgdef *md) {
- h->msgs_len = 1;
- h->msgs_size = 4;
- h->msgs = malloc(h->msgs_size * sizeof(*h->msgs));
- h->top = &h->stack[0];
- h->limit = &h->stack[UPB_MAX_TYPE_DEPTH];
- h->toplevel_msgdef = md;
- h->should_jit = true;
- if (md) upb_msgdef_ref(md);
- h->top->msgent_index = 0;
- h->top->msgdef = md;
- h->msgent = &h->msgs[0];
- upb_msgent_init(h->msgent);
-}
+/* upb_mhandlers **************************************************************/
-void upb_handlers_uninit(upb_handlers *h) {
- for (int i = 0; i < h->msgs_len; i++) {
- upb_inttable_free(&h->msgs[i].fieldtab);
- free(h->msgs[i].tablearray);
- }
- free(h->msgs);
- upb_msgdef_unref(h->toplevel_msgdef);
+static upb_mhandlers *upb_mhandlers_new() {
+ upb_mhandlers *m = malloc(sizeof(*m));
+ upb_inttable_init(&m->fieldtab, 8, sizeof(upb_fhandlers));
+ m->startmsg = &upb_startmsg_nop;
+ m->endmsg = &upb_endmsg_nop;
+ m->tablearray = NULL;
+ m->is_group = false;
+ return m;
}
-static upb_fhandlers *upb_handlers_getorcreate_without_fval(
- upb_handlers *h, upb_field_number_t fieldnum, upb_fieldtype_t type, bool repeated) {
- uint32_t tag = fieldnum << 3 | upb_types[type].native_wire_type;
- upb_fhandlers *f = upb_inttable_lookup(&h->msgent->fieldtab, tag);
- if (!f) {
- upb_fhandlers new_f = {false, type, repeated,
- repeated && upb_isprimitivetype(type), fieldnum, -1, UPB_NO_VALUE,
- {&upb_value_nop}, &upb_endsubmsg_nop, 0, 0, 0, NULL};
- if (upb_issubmsgtype(type)) new_f.cb.startsubmsg = &upb_startsubmsg_nop;
- upb_inttable_insert(&h->msgent->fieldtab, tag, &new_f);
-
- f = upb_inttable_lookup(&h->msgent->fieldtab, tag);
- assert(f);
- }
+static upb_fhandlers *_upb_mhandlers_newfield(upb_mhandlers *m, uint32_t n,
+ upb_fieldtype_t type,
+ bool repeated) {
+ uint32_t tag = n << 3 | upb_types[type].native_wire_type;
+ upb_fhandlers *f = upb_inttable_lookup(&m->fieldtab, tag);
+ if (f) abort();
+ upb_fhandlers new_f = {false, type, repeated,
+ repeated && upb_isprimitivetype(type), n, NULL, UPB_NO_VALUE,
+ &upb_value_nop, &upb_startsubmsg_nop, &upb_endsubmsg_nop, 0, 0, 0, NULL};
+ if (upb_issubmsgtype(type)) new_f.startsubmsg = &upb_startsubmsg_nop;
+ upb_inttable_insert(&m->fieldtab, tag, &new_f);
+ f = upb_inttable_lookup(&m->fieldtab, tag);
+ assert(f);
assert(f->type == type);
return f;
}
-static upb_fhandlers *upb_handlers_getorcreate(
- upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated, upb_value fval) {
- upb_fhandlers *f =
- upb_handlers_getorcreate_without_fval(h, fieldnum, type, repeated);
- f->fval = fval;
- return f;
+upb_fhandlers *upb_mhandlers_newfield(upb_mhandlers *m, uint32_t n,
+ upb_fieldtype_t type, bool repeated) {
+ assert(type != UPB_TYPE(MESSAGE));
+ assert(type != UPB_TYPE(GROUP));
+ return _upb_mhandlers_newfield(m, n, type, repeated);
}
-void upb_register_startend(upb_handlers *h, upb_startmsg_handler *startmsg,
- upb_endmsg_handler *endmsg) {
- h->msgent->startmsg = startmsg ? startmsg : &upb_startmsg_nop;
- h->msgent->endmsg = endmsg ? endmsg : &upb_endmsg_nop;
+upb_fhandlers *upb_mhandlers_newsubmsgfield(upb_mhandlers *m, uint32_t n,
+ upb_fieldtype_t type, bool repeated,
+ upb_mhandlers *subm) {
+ assert(type == UPB_TYPE(MESSAGE) || type == UPB_TYPE(GROUP));
+ assert(subm);
+ upb_fhandlers *f = _upb_mhandlers_newfield(m, n, type, repeated);
+ f->submsg = subm;
+ if (type == UPB_TYPE(GROUP))
+ _upb_mhandlers_newfield(subm, n, UPB_TYPE_ENDGROUP, false);
+ return f;
}
-// TODO:
-// void upb_register_unknownval(upb_handlers *h,
-// upb_unknownval_handler *unknown);
-// bool upb_handlers_link(upb_handlers *h, upb_fielddef *f);
-// void upb_register_path_value(upb_handlers *h, const char *path,
-// upb_value_handler *value, upb_value fval);
-
-void upb_register_all(upb_handlers *h, upb_startmsg_handler *start,
- upb_endmsg_handler *end,
- upb_value_handler *value,
- upb_startsubmsg_handler *startsubmsg,
- upb_endsubmsg_handler *endsubmsg) {
- upb_register_startend(h, start, end);
- //upb_register_unknownval(h, unknown);
- upb_msgdef *m = h->top->msgdef;
+typedef struct {
+ upb_strtable_entry e;
+ upb_mhandlers *mh;
+} upb_mtab_ent;
+
+static upb_mhandlers *upb_regmsg_dfs(upb_handlers *h, upb_msgdef *m,
+ upb_onmsgreg *msgreg_cb,
+ upb_onfieldreg *fieldreg_cb,
+ void *closure, upb_strtable *mtab) {
+ upb_mhandlers *mh = upb_handlers_newmsg(h);
+ upb_mtab_ent e = {{m->base.fqname, 0}, mh};
+ printf("Inserting: " UPB_STRFMT "\n", UPB_STRARG(m->base.fqname));
+ upb_strtable_insert(mtab, &e.e);
+ if (msgreg_cb) msgreg_cb(closure, mh, m);
upb_msg_iter i;
for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
upb_fielddef *f = upb_msg_iter_field(i);
- upb_value fval;
- upb_value_setfielddef(&fval, f);
+ upb_fhandlers *fh;
if (upb_issubmsg(f)) {
- upb_handlers_push(h, f, startsubmsg, endsubmsg, fval, false);
- upb_register_all(h, start, end, value, startsubmsg, endsubmsg);
- upb_handlers_pop(h, f);
+ upb_mhandlers *sub_mh;
+ upb_mtab_ent *subm_ent;
+ // The table lookup is necessary to break the DFS for type cycles.
+ printf("Testing: " UPB_STRFMT "\n", UPB_STRARG(f->def->fqname));
+ if ((subm_ent = upb_strtable_lookup(mtab, f->def->fqname)) != NULL) {
+ sub_mh = subm_ent->mh;
+ } else {
+ sub_mh = upb_regmsg_dfs(h, upb_downcast_msgdef(f->def), msgreg_cb,
+ fieldreg_cb, closure, mtab);
+ }
+ fh = upb_mhandlers_newsubmsgfield(
+ mh, f->number, f->type, upb_isarray(f), sub_mh);
} else {
- upb_register_value(h, f, value, fval);
+ fh = upb_mhandlers_newfield(mh, f->number, f->type, upb_isarray(f));
}
+ if (fieldreg_cb) fieldreg_cb(closure, fh, f);
}
+ return mh;
}
-void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated,
- upb_value_handler *value, upb_value fval) {
- upb_handlers_getorcreate(h, fieldnum, type, repeated, fval)->cb.value =
- value ? value : &upb_value_nop;
+upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m,
+ upb_onmsgreg *msgreg_cb,
+ upb_onfieldreg *fieldreg_cb,
+ void *closure) {
+ upb_strtable mtab;
+ upb_strtable_init(&mtab, 8, sizeof(upb_mtab_ent));
+ upb_mhandlers *ret =
+ upb_regmsg_dfs(h, m, msgreg_cb, fieldreg_cb, closure, &mtab);
+ upb_strtable_free(&mtab);
+ return ret;
}
-void upb_register_value(upb_handlers *h, upb_fielddef *f,
- upb_value_handler *value, upb_value fval) {
- assert(f->msgdef == h->top->msgdef);
- upb_register_typed_value(h, f->number, f->type, upb_isarray(f), value, fval);
-}
-void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated,
- upb_startsubmsg_handler *start,
- upb_endsubmsg_handler *end,
- upb_value fval) {
- upb_fhandlers *f = upb_handlers_getorcreate(h, fieldnum, type, repeated, fval);
- f->cb.startsubmsg = start ? start : &upb_startsubmsg_nop;
- f->endsubmsg = end ? end : &upb_endsubmsg_nop;
-}
+/* upb_handlers ***************************************************************/
-void upb_handlers_typed_link(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated, int frames) {
- assert(frames <= (h->top - h->stack));
- upb_fhandlers *f =
- upb_handlers_getorcreate_without_fval(h, fieldnum, type, repeated);
- f->msgent_index = (h->top - frames)->msgent_index;
+void upb_handlers_init(upb_handlers *h) {
+ h->msgs_len = 0;
+ h->msgs_size = 4;
+ h->msgs = malloc(h->msgs_size * sizeof(*h->msgs));
+ h->should_jit = true;
}
-void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated) {
- upb_fhandlers *f =
- upb_handlers_getorcreate_without_fval(h, fieldnum, type, repeated);
- if (h->top == h->limit) abort(); // TODO: make growable.
- ++h->top;
- if (f->msgent_index == -1) {
- // Need to push a new msgent.
- if (h->msgs_size == h->msgs_len) {
- h->msgs_size *= 2;
- h->msgs = realloc(h->msgs, h->msgs_size * sizeof(*h->msgs));
- }
- f->msgent_index = h->msgs_len++;
- h->msgent = &h->msgs[f->msgent_index];
- upb_msgent_init(h->msgent);
- } else {
- h->msgent = &h->msgs[f->msgent_index];
- }
- h->top->msgent_index = f->msgent_index;
- if (h->toplevel_msgdef) {
- upb_fielddef *f = upb_msgdef_itof((h->top - 1)->msgdef, fieldnum);
- assert(f);
- h->top->msgdef = upb_downcast_msgdef(f->def);
- }
- if (type == UPB_TYPE(GROUP)) {
- // Insert a fieldent for ENDGROUP so we can easily dispatch endgroup when
- // we see it in the submessage.
- // TODO: assert that no other fields in the group are registered with the
- // same name or number.
- upb_register_typed_submsg(h, fieldnum, UPB_TYPE_ENDGROUP, false, NULL, NULL,
- UPB_NO_VALUE);
- h->msgent->is_group = true;
+void upb_handlers_uninit(upb_handlers *h) {
+ for (int i = 0; i < h->msgs_len; i++) {
+ upb_mhandlers *mh = h->msgs[i];
+ upb_inttable_free(&mh->fieldtab);
+ free(mh->tablearray);
+ free(mh);
}
+ free(h->msgs);
}
-void upb_handlers_push(upb_handlers *h, upb_fielddef *f,
- upb_startsubmsg_handler *start,
- upb_endsubmsg_handler *end, upb_value fval,
- bool delegate) {
- assert(f->msgdef == h->top->msgdef);
- (void)delegate; // TODO
- upb_register_typed_submsg(h, f->number, f->type, upb_isarray(f), start, end, fval);
- upb_handlers_typed_push(h, f->number, f->type, upb_isarray(f));
-}
-
-void upb_handlers_typed_pop(upb_handlers *h) {
- assert(h->top > h->stack);
- --h->top;
- h->msgent = &h->msgs[h->top->msgent_index];
+upb_mhandlers *upb_handlers_newmsg(upb_handlers *h) {
+ if (h->msgs_len == h->msgs_size) {
+ h->msgs_size *= 2;
+ h->msgs = realloc(h->msgs, h->msgs_size * sizeof(*h->msgs));
+ }
+ upb_mhandlers *mh = upb_mhandlers_new();
+ h->msgs[h->msgs_len++] = mh;
+ return mh;
}
-void upb_handlers_pop(upb_handlers *h, upb_fielddef *f) {
- (void)f; // TODO: Check that this matches the corresponding push.
- upb_handlers_typed_pop(h);
-}
/* upb_dispatcher *************************************************************/
static upb_fhandlers toplevel_f = {
false, UPB_TYPE(GROUP), false, false, 0,
- 0, // msgent_index
+ NULL, // submsg
#ifdef NDEBUG
{{0}},
#else
{{0}, UPB_VALUETYPE_RAW},
#endif
- {NULL}, NULL, 0, 0, 0, NULL};
+ NULL, NULL, NULL, 0, 0, 0, NULL};
void upb_dispatcher_init(upb_dispatcher *d, upb_handlers *h) {
d->handlers = h;
- for (int i = 0; i < h->msgs_len; i++)
- upb_inttable_compact(&h->msgs[i].fieldtab);
+ for (int i = 0; i < h->msgs_len; i++) {
+ upb_mhandlers *m = h->msgs[i];
+ upb_inttable_compact(&m->fieldtab);
+ }
d->stack[0].f = &toplevel_f;
d->limit = &d->stack[UPB_MAX_NESTING];
upb_status_init(&d->status);
}
void upb_dispatcher_reset(upb_dispatcher *d, void *top_closure, uint32_t top_end_offset) {
- d->msgent = &d->handlers->msgs[0];
+ d->msgent = d->handlers->msgs[0];
d->dispatch_table = &d->msgent->fieldtab;
d->current_depth = 0;
d->skip_depth = INT_MAX;
@@ -296,7 +236,7 @@ upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, upb_fhandlers *f,
size_t userval) {
++d->current_depth;
if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG;
- upb_sflow_t sflow = f->cb.startsubmsg(d->top->closure, f->fval);
+ upb_sflow_t sflow = f->startsubmsg(d->top->closure, f->fval);
if (sflow.flow != UPB_CONTINUE) {
d->noframe_depth = d->current_depth;
d->skip_depth = (sflow.flow == UPB_BREAK) ?
@@ -315,7 +255,7 @@ upb_flow_t upb_dispatch_startsubmsg(upb_dispatcher *d, upb_fhandlers *f,
d->top->end_offset = userval;
d->top->closure = sflow.closure;
d->top->is_packed = false;
- d->msgent = upb_handlers_getmsgent(d->handlers, f);
+ d->msgent = f->submsg;
d->dispatch_table = &d->msgent->fieldtab;
return upb_dispatch_startmsg(d);
}
@@ -329,7 +269,8 @@ upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d) {
upb_fhandlers *old_f = d->top->f;
d->msgent->endmsg(d->top->closure, &d->status);
--d->top;
- d->msgent = upb_handlers_getmsgent(d->handlers, d->top->f);
+ d->msgent = d->top->f->submsg;
+ if (!d->msgent) d->msgent = d->handlers->msgs[0];
d->dispatch_table = &d->msgent->fieldtab;
d->noframe_depth = INT_MAX;
if (!upb_dispatcher_skipping(d)) d->skip_depth = INT_MAX;
diff --git a/src/upb_handlers.h b/src/upb_handlers.h
index f36f1dd..d155b2b 100644
--- a/src/upb_handlers.h
+++ b/src/upb_handlers.h
@@ -108,33 +108,12 @@ upb_flow_t upb_value_nop(void *closure, upb_value fval, upb_value val);
upb_sflow_t upb_startsubmsg_nop(void *closure, upb_value fval);
upb_flow_t upb_endsubmsg_nop(void *closure, upb_value fval);
-struct _upb_decoder;
-typedef struct _upb_fieldent {
- bool junk;
- upb_fieldtype_t type;
- bool repeated;
- bool is_repeated_primitive;
- uint32_t number;
- // For upb_issubmsg(f) only, the index into the msgdef array of the submsg.
- // -1 if unset (indicates that submsg should be skipped).
- int32_t msgent_index;
- upb_value fval;
- union {
- upb_value_handler *value;
- upb_startsubmsg_handler *startsubmsg;
- } cb;
- upb_endsubmsg_handler *endsubmsg;
- uint32_t jit_pclabel;
- uint32_t jit_pclabel_notypecheck;
- uint32_t jit_submsg_done_pclabel;
- void (*decode)(struct _upb_decoder *d, struct _upb_fieldent *f);
-} upb_fhandlers;
-
-typedef struct _upb_msgent {
+// Structure definitions. Do not access any fields directly! Accessors are
+// provided for the fields that may be get/set.
+typedef struct _upb_mhandlers {
upb_startmsg_handler *startmsg;
upb_endmsg_handler *endmsg;
- // Maps field number -> upb_fhandlers.
- upb_inttable fieldtab;
+ upb_inttable fieldtab; // Maps field number -> upb_fhandlers.
uint32_t jit_startmsg_pclabel;
uint32_t jit_endofbuf_pclabel;
uint32_t jit_endofmsg_pclabel;
@@ -147,25 +126,33 @@ typedef struct _upb_msgent {
void **tablearray;
} upb_mhandlers;
-typedef struct {
- upb_msgdef *msgdef;
- int msgent_index;
-} upb_handlers_frame;
+struct _upb_decoder;
+typedef struct _upb_fieldent {
+ bool junk;
+ upb_fieldtype_t type;
+ bool repeated;
+ bool is_repeated_primitive;
+ uint32_t number;
+ upb_mhandlers *submsg; // Must be set iff upb_issubmsgtype(type) == true.
+ upb_value fval;
+ upb_value_handler *value;
+ upb_startsubmsg_handler *startsubmsg;
+ upb_endsubmsg_handler *endsubmsg;
+ uint32_t jit_pclabel;
+ uint32_t jit_pclabel_notypecheck;
+ uint32_t jit_submsg_done_pclabel;
+ void (*decode)(struct _upb_decoder *d, struct _upb_fieldent *f);
+} upb_fhandlers;
struct _upb_handlers {
// Array of msgdefs, [0]=toplevel.
- upb_mhandlers *msgs;
+ upb_mhandlers **msgs;
int msgs_len, msgs_size;
- upb_msgdef *toplevel_msgdef; // We own a ref.
- upb_mhandlers *msgent;
- upb_handlers_frame stack[UPB_MAX_TYPE_DEPTH], *top, *limit;
bool should_jit;
};
typedef struct _upb_handlers upb_handlers;
-// The handlers object takes a ref on md. md can be NULL iff the client calls
-// only upb_*_typed_*() (only upb_symtab should do this).
-void upb_handlers_init(upb_handlers *h, upb_msgdef *md);
+void upb_handlers_init(upb_handlers *h);
void upb_handlers_uninit(upb_handlers *h);
// The startsubmsg handler needs to also pass a closure to the submsg.
@@ -180,75 +167,84 @@ INLINE upb_sflow_t UPB_SFLOW(upb_flow_t flow, void *closure) {
#define UPB_CONTINUE_WITH(c) UPB_SFLOW(UPB_CONTINUE, c)
#define UPB_S_BREAK UPB_SFLOW(UPB_BREAK, NULL)
-// Functions to register the above handlers.
-void upb_register_startend(upb_handlers *h, upb_startmsg_handler *startmsg,
- upb_endmsg_handler *endmsg);
-void upb_register_value(upb_handlers *h, upb_fielddef *f,
- upb_value_handler *value, upb_value fval);
-
-// To register handlers for a submessage, push the fielddef and pop it
-// when you're done. This can be used to delegate a submessage to a
-// different processing component which does not need to be aware whether
-// it is at the top level or not.
-void upb_handlers_push(upb_handlers *h, upb_fielddef *f,
- upb_startsubmsg_handler *start,
- upb_endsubmsg_handler *end, upb_value fval,
- bool delegate);
-void upb_handlers_pop(upb_handlers *h, upb_fielddef *f);
-
-// In the case where types are self-recursive or mutually recursive, you can
-// use this function which will link a set of handlers to a set that is
-// already on our stack. This allows us to handle a tree of arbitrary
-// depth without having to register an arbitrary number of levels of handlers.
-// Returns "true" if the given type is indeed on the stack already and was
-// linked.
+// Appends a new message to the graph of handlers and returns it. This message
+// can be obtained later at index upb_handlers_msgcount()-1. All handlers will
+// be initialized to no-op handlers.
+upb_mhandlers *upb_handlers_newmsg(upb_handlers *h);
+upb_mhandlers *upb_handlers_getmsg(upb_handlers *h, int index);
+
+// Creates a new field with the given name and number. There must not be an
+// existing field with either this name or number or abort() will be called.
+// TODO: this should take a name also.
+upb_fhandlers *upb_mhandlers_newfield(upb_mhandlers *m, uint32_t n,
+ upb_fieldtype_t type, bool repeated);
+// Like the previous but for MESSAGE or GROUP fields. For GROUP fields, the
+// given submessage must not have any fields with this field number.
+upb_fhandlers *upb_mhandlers_newsubmsgfield(upb_mhandlers *m, uint32_t n,
+ upb_fieldtype_t type, bool repeated,
+ upb_mhandlers *subm);
+
+// upb_mhandlers accessors.
+#define UPB_MHANDLERS_ACCESSORS(name, type) \
+ INLINE void upb_mhandlers_set ## name(upb_mhandlers *m, type v){m->name = v;} \
+ INLINE type upb_mhandlers_get ## name(upb_mhandlers *m) { return m->name; }
+UPB_MHANDLERS_ACCESSORS(startmsg, upb_startmsg_handler*);
+UPB_MHANDLERS_ACCESSORS(endmsg, upb_endmsg_handler*);
+
+// upb_fhandlers accessors
+#define UPB_FHANDLERS_ACCESSORS(name, type) \
+ INLINE void upb_fhandlers_set ## name(upb_fhandlers *f, type v){f->name = v;} \
+ INLINE type upb_fhandlers_get ## name(upb_fhandlers *f) { return f->name; }
+UPB_FHANDLERS_ACCESSORS(fval, upb_value)
+UPB_FHANDLERS_ACCESSORS(value, upb_value_handler*)
+UPB_FHANDLERS_ACCESSORS(startsubmsg, upb_startsubmsg_handler*)
+UPB_FHANDLERS_ACCESSORS(endsubmsg, upb_endsubmsg_handler*)
+UPB_FHANDLERS_ACCESSORS(submsg, upb_mhandlers*)
+
+// Convenience function for registering handlers for all messages and
+// fields in a msgdef and all its children. For every registered message
+// "msgreg_cb" will be called with the newly-created mhandlers, and likewise
+// with "fieldreg_cb"
//
-// If more than one message of this type is on the stack, it chooses the
-// one that is deepest in the tree (if necessary, we could give the caller
-// more control over this).
-bool upb_handlers_link(upb_handlers *h, upb_fielddef *f);
-
-// Convenience function for registering the given handler for the given
-// field path. This will overwrite any startsubmsg handlers that were
-// previously registered along the path. These can be overwritten again
-// later if desired.
-// TODO: upb_register_path_submsg()?
-void upb_register_path_value(upb_handlers *h, const char *path,
- upb_value_handler *value, upb_value fval);
-
-// Convenience function for registering a single set of handlers on every
-// message in our hierarchy. mvals are bound to upb_msgdef* and fvals are
-// bound to upb_fielddef*. Any of the handlers can be NULL.
-void upb_register_all(upb_handlers *h, upb_startmsg_handler *start,
- upb_endmsg_handler *end,
- upb_value_handler *value,
- upb_startsubmsg_handler *startsubmsg,
- upb_endsubmsg_handler *endsubmsg);
-
-// TODO: for clients that want to increase efficiency by preventing bytesrcs
-// from automatically being converted to strings in the value callback.
-// INLINE void upb_handlers_use_bytesrcs(upb_handlers *h, bool use_bytesrcs);
-
-// Low-level functions -- internal-only.
-void upb_register_typed_value(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated,
- upb_value_handler *value, upb_value fval);
-void upb_register_typed_submsg(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated,
- upb_startsubmsg_handler *start,
- upb_endsubmsg_handler *end,
- upb_value fval);
-void upb_handlers_typed_link(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated, int frames);
-void upb_handlers_typed_push(upb_handlers *h, upb_field_number_t fieldnum,
- upb_fieldtype_t type, bool repeated);
-void upb_handlers_typed_pop(upb_handlers *h);
-
-INLINE upb_mhandlers *upb_handlers_getmsgent(upb_handlers *h, upb_fhandlers *f) {
- assert(f->msgent_index != -1);
- return &h->msgs[f->msgent_index];
+// See upb_handlers_reghandlerset() below for an example.
+typedef void upb_onmsgreg(void *closure, upb_mhandlers *mh, upb_msgdef *m);
+typedef void upb_onfieldreg(void *closure, upb_fhandlers *mh, upb_fielddef *m);
+upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m,
+ upb_onmsgreg *msgreg_cb,
+ upb_onfieldreg *fieldreg_cb,
+ void *closure);
+
+// Convenience function for registering a set of handlers for all messages and
+// fields in a msgdef and its children, with the fval bound to the upb_fielddef.
+// Any of the handlers may be NULL, in which case no callback will be set and
+// the nop callback will be used.
+typedef struct {
+ upb_startmsg_handler *startmsg;
+ upb_endmsg_handler *endmsg;
+ upb_value_handler *value;
+ upb_startsubmsg_handler *startsubmsg;
+ upb_endsubmsg_handler *endsubmsg;
+} upb_handlerset;
+
+INLINE void upb_onmreg_hset(void *c, upb_mhandlers *mh, upb_msgdef *m) {
+ (void)m;
+ upb_handlerset *hs = (upb_handlerset*)c;
+ if (hs->startmsg) upb_mhandlers_setstartmsg(mh, hs->startmsg);
+ if (hs->endmsg) upb_mhandlers_setendmsg(mh, hs->endmsg);
+}
+INLINE void upb_onfreg_hset(void *c, upb_fhandlers *fh, upb_fielddef *f) {
+ upb_handlerset *hs = (upb_handlerset*)c;
+ if (hs->value) upb_fhandlers_setvalue(fh, hs->value);
+ if (hs->startsubmsg) upb_fhandlers_setstartsubmsg(fh, hs->startsubmsg);
+ if (hs->endsubmsg) upb_fhandlers_setendsubmsg(fh, hs->endsubmsg);
+ upb_value val;
+ upb_value_setfielddef(&val, f);
+ upb_fhandlers_setfval(fh, val);
+}
+INLINE upb_mhandlers *upb_handlers_reghandlerset(upb_handlers *h, upb_msgdef *m,
+ upb_handlerset *hs) {
+ return upb_handlers_regmsgdef(h, m, &upb_onmreg_hset, &upb_onfreg_hset, hs);
}
-upb_fhandlers *upb_handlers_lookup(upb_inttable *dispatch_table, upb_field_number_t fieldnum);
/* upb_dispatcher *************************************************************/
@@ -338,7 +334,7 @@ upb_flow_t upb_dispatch_endsubmsg(upb_dispatcher *d);
INLINE upb_flow_t upb_dispatch_value(upb_dispatcher *d, upb_fhandlers *f,
upb_value val) {
if (upb_dispatcher_skipping(d)) return UPB_SKIPSUBMSG;
- upb_flow_t flow = f->cb.value(d->top->closure, f->fval, val);
+ upb_flow_t flow = f->value(d->top->closure, f->fval, val);
if (flow != UPB_CONTINUE) {
d->noframe_depth = d->current_depth + 1;
d->skip_depth = (flow == UPB_BREAK) ? d->delegated_depth : d->current_depth;
diff --git a/src/upb_msg.c b/src/upb_msg.c
index 98147c8..1115673 100644
--- a/src/upb_msg.c
+++ b/src/upb_msg.c
@@ -461,55 +461,49 @@ upb_sflow_t upb_msgsink_startsubmsg_r(void *_m, upb_value _fval) {
return UPB_CONTINUE_WITH(upb_msg_appendmsg(m, &f, &md));
}
-void upb_msg_regdhandlers(upb_handlers *h) {
- upb_register_all(h, NULL, NULL, NULL, NULL, NULL);
- for (int i = 0; i < h->msgs_len; i++) {
- upb_mhandlers *m = &h->msgs[i];
- upb_inttable_iter iter = upb_inttable_begin(&m->fieldtab);
- for(; !upb_inttable_done(iter);
- iter = upb_inttable_next(&m->fieldtab, iter)) {
- upb_fhandlers *fe = upb_inttable_iter_value(iter);
- if (fe->type == UPB_TYPE_ENDGROUP) continue;
- upb_fielddef *f = upb_value_getfielddef(fe->fval);
- uint16_t msg_size = 0;
- uint8_t set_flags_bytes = 0;
- if (upb_issubmsg(f)) {
- upb_msgdef *md = upb_downcast_msgdef(f->def);
- msg_size = md->size;
- set_flags_bytes = md->set_flags_bytes;
- }
- upb_value_setuint64(&fe->fval,
- upb_msgsink_packfval(f->set_bit_offset, f->set_bit_mask,
- f->byte_offset, msg_size, set_flags_bytes));
+INLINE void upb_msg_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) {
+ (void)c;
+ uint16_t msg_size = 0;
+ uint8_t set_flags_bytes = 0;
+ if (upb_issubmsg(f)) {
+ upb_msgdef *md = upb_downcast_msgdef(f->def);
+ msg_size = md->size;
+ set_flags_bytes = md->set_flags_bytes;
+ }
+ upb_value_setuint64(&fh->fval,
+ upb_msgsink_packfval(f->set_bit_offset, f->set_bit_mask,
+ f->byte_offset, msg_size, set_flags_bytes));
#define CASE(upb_type, type) \
- case UPB_TYPE(upb_type): \
- fe->cb.value = upb_isarray(f) ? \
- upb_msgsink_ ## type ## value_r : upb_msgsink_ ## type ## value; \
- break;
- switch (f->type) {
- CASE(DOUBLE, double)
- CASE(FLOAT, float)
- CASE(INT32, int32)
- CASE(INT64, int64)
- CASE(UINT32, uint32)
- CASE(UINT64, uint64)
- CASE(SINT32, int32)
- CASE(SINT64, int64)
- CASE(FIXED32, uint32)
- CASE(FIXED64, uint64)
- CASE(SFIXED32, int32)
- CASE(SFIXED64, int64)
- CASE(BOOL, bool)
- CASE(ENUM, int32)
- CASE(STRING, str)
- CASE(BYTES, str)
+case UPB_TYPE(upb_type): \
+ fh->value = upb_isarray(f) ? \
+ upb_msgsink_ ## type ## value_r : upb_msgsink_ ## type ## value; \
+ break;
+ switch (f->type) {
+ CASE(DOUBLE, double)
+ CASE(FLOAT, float)
+ CASE(INT32, int32)
+ CASE(INT64, int64)
+ CASE(UINT32, uint32)
+ CASE(UINT64, uint64)
+ CASE(SINT32, int32)
+ CASE(SINT64, int64)
+ CASE(FIXED32, uint32)
+ CASE(FIXED64, uint64)
+ CASE(SFIXED32, int32)
+ CASE(SFIXED64, int64)
+ CASE(BOOL, bool)
+ CASE(ENUM, int32)
+ CASE(STRING, str)
+ CASE(BYTES, str)
#undef CASE
- case UPB_TYPE(MESSAGE):
- case UPB_TYPE(GROUP):
- fe->cb.startsubmsg =
- upb_isarray(f) ? upb_msgsink_startsubmsg_r : upb_msgsink_startsubmsg;
- break;
- }
- }
+ case UPB_TYPE(MESSAGE):
+ case UPB_TYPE(GROUP):
+ fh->startsubmsg =
+ upb_isarray(f) ? upb_msgsink_startsubmsg_r : upb_msgsink_startsubmsg;
+ break;
}
}
+
+upb_mhandlers *upb_msg_reghandlers(upb_handlers *h, upb_msgdef *m) {
+ return upb_handlers_regmsgdef(h, m, NULL, &upb_msg_onfreg, NULL);
+}
diff --git a/src/upb_msg.h b/src/upb_msg.h
index 68ba13a..33f5d1c 100644
--- a/src/upb_msg.h
+++ b/src/upb_msg.h
@@ -277,11 +277,7 @@ INLINE void upb_msg_clear(upb_msg *msg, upb_msgdef *md) {
// Registers handlers for populating a msg for the given upb_msgdef.
// The upb_msg itself must be passed as the param to the src.
-void upb_msg_reghandlers(upb_handlers *h, upb_msgdef *md);
-
-// Registers handlers that are suitable for populating a msg of *any*
-// upb_msgdef ("dynamic" handlers). May be slower than upb_msg_reghandlers().
-void upb_msg_regdhandlers(upb_handlers *h);
+upb_mhandlers *upb_msg_reghandlers(upb_handlers *h, upb_msgdef *md);
void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
void *closure, upb_status *status);
diff --git a/src/upb_textprinter.c b/src/upb_textprinter.c
index 2f3a6b5..7d0a9dd 100644
--- a/src/upb_textprinter.c
+++ b/src/upb_textprinter.c
@@ -185,12 +185,13 @@ void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink,
p->indent_depth = 0;
}
-void upb_textprinter_reghandlers(upb_handlers *h) {
- upb_register_all(h,
+upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m) {
+ upb_handlerset hset = {
NULL, // startmsg
NULL, // endmsg
upb_textprinter_value,
upb_textprinter_startsubmsg,
upb_textprinter_endsubmsg
- );
+ };
+ return upb_handlers_reghandlerset(h, m, &hset);
}
diff --git a/src/upb_textprinter.h b/src/upb_textprinter.h
index f8c7f78..2d70d2e 100644
--- a/src/upb_textprinter.h
+++ b/src/upb_textprinter.h
@@ -22,7 +22,7 @@ upb_textprinter *upb_textprinter_new();
void upb_textprinter_free(upb_textprinter *p);
void upb_textprinter_reset(upb_textprinter *p, upb_bytesink *sink,
bool single_line);
-void upb_textprinter_reghandlers(upb_handlers *h);
+upb_mhandlers *upb_textprinter_reghandlers(upb_handlers *h, upb_msgdef *m);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/tests/tests.c b/tests/tests.c
index d07d495..dea535c 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -39,8 +39,9 @@ static void test_upb_jit() {
ASSERT(def);
upb_handlers h;
- upb_handlers_init(&h, upb_downcast_msgdef(def));
- upb_register_all(&h, NULL, NULL, &upb_test_onvalue, NULL, NULL);
+ upb_handlers_init(&h);
+ upb_handlerset hset = {NULL, NULL, &upb_test_onvalue, NULL, NULL};
+ upb_handlers_reghandlerset(&h, upb_downcast_msgdef(def), &hset);
upb_decoder d;
upb_decoder_init(&d, &h);
upb_decoder_uninit(&d);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback