From 3231fd0fdd64bc6355bce921a988713524726f23 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 10 May 2011 21:59:46 -0700 Subject: Vastly improved/simplified the upb_handlers API. --- benchmarks/parsestream.upb_table.c | 5 +- benchmarks/parsetostruct.upb_table.c | 4 +- src/upb_decoder.c | 2 +- src/upb_def.c | 204 +++++++++++++------------- src/upb_def.h | 3 +- src/upb_glue.c | 10 +- src/upb_handlers.c | 277 ++++++++++++++--------------------- src/upb_handlers.h | 204 +++++++++++++------------- src/upb_msg.c | 90 ++++++------ src/upb_msg.h | 6 +- src/upb_textprinter.c | 7 +- src/upb_textprinter.h | 2 +- tests/tests.c | 5 +- 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); -- cgit v1.2.3